Blame sysdeps/generic/unwind-pe.h

Packit Service 82fcde
/* Exception handling and frame unwind runtime interface routines.
Packit Service 82fcde
   Copyright (C) 2001-2018 Free Software Foundation, Inc.
Packit Service 82fcde
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* @@@ Really this should be out of line, but this also causes link
Packit Service 82fcde
   compatibility problems with the base ABI.  This is slightly better
Packit Service 82fcde
   than duplicating code, however.  */
Packit Service 82fcde
Packit Service 82fcde
/* If using C++, references to abort have to be qualified with std::.  */
Packit Service 82fcde
#ifdef __cplusplus
Packit Service 82fcde
#define __gxx_abort std::abort
Packit Service 82fcde
#else
Packit Service 82fcde
#define __gxx_abort abort
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Pointer encodings, from dwarf2.h.  */
Packit Service 82fcde
#define DW_EH_PE_absptr         0x00
Packit Service 82fcde
#define DW_EH_PE_omit           0xff
Packit Service 82fcde
Packit Service 82fcde
#define DW_EH_PE_uleb128        0x01
Packit Service 82fcde
#define DW_EH_PE_udata2         0x02
Packit Service 82fcde
#define DW_EH_PE_udata4         0x03
Packit Service 82fcde
#define DW_EH_PE_udata8         0x04
Packit Service 82fcde
#define DW_EH_PE_sleb128        0x09
Packit Service 82fcde
#define DW_EH_PE_sdata2         0x0A
Packit Service 82fcde
#define DW_EH_PE_sdata4         0x0B
Packit Service 82fcde
#define DW_EH_PE_sdata8         0x0C
Packit Service 82fcde
#define DW_EH_PE_signed         0x08
Packit Service 82fcde
Packit Service 82fcde
#define DW_EH_PE_pcrel          0x10
Packit Service 82fcde
#define DW_EH_PE_textrel        0x20
Packit Service 82fcde
#define DW_EH_PE_datarel        0x30
Packit Service 82fcde
#define DW_EH_PE_funcrel        0x40
Packit Service 82fcde
#define DW_EH_PE_aligned        0x50
Packit Service 82fcde
Packit Service 82fcde
#define DW_EH_PE_indirect	0x80
Packit Service 82fcde

Packit Service 82fcde
Packit Service 82fcde
#if defined(_LIBC)
Packit Service 82fcde
Packit Service 82fcde
/* Prototypes.  */
Packit Service 82fcde
extern unsigned int size_of_encoded_value (unsigned char encoding)
Packit Service 82fcde
  attribute_hidden;
Packit Service 82fcde
Packit Service 82fcde
extern const unsigned char *read_encoded_value_with_base
Packit Service 82fcde
  (unsigned char encoding, _Unwind_Ptr base,
Packit Service 82fcde
   const unsigned char *p, _Unwind_Ptr *val)
Packit Service 82fcde
  attribute_hidden;
Packit Service 82fcde
Packit Service 82fcde
extern const unsigned char * read_encoded_value
Packit Service 82fcde
  (struct _Unwind_Context *context, unsigned char encoding,
Packit Service 82fcde
   const unsigned char *p, _Unwind_Ptr *val)
Packit Service 82fcde
  attribute_hidden;
Packit Service 82fcde
Packit Service 82fcde
extern const unsigned char * read_uleb128 (const unsigned char *p,
Packit Service 82fcde
					   _Unwind_Word *val)
Packit Service 82fcde
  attribute_hidden;
Packit Service 82fcde
extern const unsigned char * read_sleb128 (const unsigned char *p,
Packit Service 82fcde
					   _Unwind_Sword *val)
Packit Service 82fcde
  attribute_hidden;
Packit Service 82fcde
Packit Service 82fcde
#endif
Packit Service 82fcde
#if defined(_LIBC) && defined(_LIBC_DEFINITIONS)
Packit Service 82fcde
Packit Service 82fcde
#ifdef _LIBC
Packit Service 82fcde
#define STATIC
Packit Service 82fcde
#else
Packit Service 82fcde
#define STATIC static
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Given an encoding, return the number of bytes the format occupies.
Packit Service 82fcde
   This is only defined for fixed-size encodings, and so does not
Packit Service 82fcde
   include leb128.  */
Packit Service 82fcde
Packit Service 82fcde
STATIC unsigned int
Packit Service 82fcde
size_of_encoded_value (unsigned char encoding)
Packit Service 82fcde
{
Packit Service 82fcde
  if (encoding == DW_EH_PE_omit)
Packit Service 82fcde
    return 0;
Packit Service 82fcde
Packit Service 82fcde
  switch (encoding & 0x07)
Packit Service 82fcde
    {
Packit Service 82fcde
    case DW_EH_PE_absptr:
Packit Service 82fcde
      return sizeof (void *);
Packit Service 82fcde
    case DW_EH_PE_udata2:
Packit Service 82fcde
      return 2;
Packit Service 82fcde
    case DW_EH_PE_udata4:
Packit Service 82fcde
      return 4;
Packit Service 82fcde
    case DW_EH_PE_udata8:
Packit Service 82fcde
      return 8;
Packit Service 82fcde
    }
Packit Service 82fcde
  __gxx_abort ();
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifndef NO_BASE_OF_ENCODED_VALUE
Packit Service 82fcde
Packit Service 82fcde
/* Given an encoding and an _Unwind_Context, return the base to which
Packit Service 82fcde
   the encoding is relative.  This base may then be passed to
Packit Service 82fcde
   read_encoded_value_with_base for use when the _Unwind_Context is
Packit Service 82fcde
   not available.  */
Packit Service 82fcde
Packit Service 82fcde
STATIC _Unwind_Ptr
Packit Service 82fcde
base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
Packit Service 82fcde
{
Packit Service 82fcde
  if (encoding == DW_EH_PE_omit)
Packit Service 82fcde
    return 0;
Packit Service 82fcde
Packit Service 82fcde
  switch (encoding & 0x70)
Packit Service 82fcde
    {
Packit Service 82fcde
    case DW_EH_PE_absptr:
Packit Service 82fcde
    case DW_EH_PE_pcrel:
Packit Service 82fcde
    case DW_EH_PE_aligned:
Packit Service 82fcde
      return 0;
Packit Service 82fcde
Packit Service 82fcde
    case DW_EH_PE_textrel:
Packit Service 82fcde
      return _Unwind_GetTextRelBase (context);
Packit Service 82fcde
    case DW_EH_PE_datarel:
Packit Service 82fcde
      return _Unwind_GetDataRelBase (context);
Packit Service 82fcde
    case DW_EH_PE_funcrel:
Packit Service 82fcde
      return _Unwind_GetRegionStart (context);
Packit Service 82fcde
    }
Packit Service 82fcde
  __gxx_abort ();
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Read an unsigned leb128 value from P, store the value in VAL, return
Packit Service 82fcde
   P incremented past the value.  We assume that a word is large enough to
Packit Service 82fcde
   hold any value so encoded; if it is smaller than a pointer on some target,
Packit Service 82fcde
   pointers should not be leb128 encoded on that target.  */
Packit Service 82fcde
Packit Service 82fcde
STATIC const unsigned char *
Packit Service 82fcde
read_uleb128 (const unsigned char *p, _Unwind_Word *val)
Packit Service 82fcde
{
Packit Service 82fcde
  unsigned int shift = 0;
Packit Service 82fcde
  unsigned char byte;
Packit Service 82fcde
  _Unwind_Word result;
Packit Service 82fcde
Packit Service 82fcde
  result = 0;
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      byte = *p++;
Packit Service 82fcde
      result |= (byte & 0x7f) << shift;
Packit Service 82fcde
      shift += 7;
Packit Service 82fcde
    }
Packit Service 82fcde
  while (byte & 0x80);
Packit Service 82fcde
Packit Service 82fcde
  *val = result;
Packit Service 82fcde
  return p;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Similar, but read a signed leb128 value.  */
Packit Service 82fcde
Packit Service 82fcde
STATIC const unsigned char *
Packit Service 82fcde
read_sleb128 (const unsigned char *p, _Unwind_Sword *val)
Packit Service 82fcde
{
Packit Service 82fcde
  unsigned int shift = 0;
Packit Service 82fcde
  unsigned char byte;
Packit Service 82fcde
  _Unwind_Word result;
Packit Service 82fcde
Packit Service 82fcde
  result = 0;
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      byte = *p++;
Packit Service 82fcde
      result |= (byte & 0x7f) << shift;
Packit Service 82fcde
      shift += 7;
Packit Service 82fcde
    }
Packit Service 82fcde
  while (byte & 0x80);
Packit Service 82fcde
Packit Service 82fcde
  /* Sign-extend a negative value.  */
Packit Service 82fcde
  if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
Packit Service 82fcde
    result |= -(1L << shift);
Packit Service 82fcde
Packit Service 82fcde
  *val = (_Unwind_Sword) result;
Packit Service 82fcde
  return p;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Load an encoded value from memory at P.  The value is returned in VAL;
Packit Service 82fcde
   The function returns P incremented past the value.  BASE is as given
Packit Service 82fcde
   by base_of_encoded_value for this encoding in the appropriate context.  */
Packit Service 82fcde
Packit Service 82fcde
STATIC const unsigned char *
Packit Service 82fcde
read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
Packit Service 82fcde
			      const unsigned char *p, _Unwind_Ptr *val)
Packit Service 82fcde
{
Packit Service 82fcde
  union unaligned
Packit Service 82fcde
    {
Packit Service 82fcde
      void *ptr;
Packit Service 82fcde
      unsigned u2 __attribute__ ((mode (HI)));
Packit Service 82fcde
      unsigned u4 __attribute__ ((mode (SI)));
Packit Service 82fcde
      unsigned u8 __attribute__ ((mode (DI)));
Packit Service 82fcde
      signed s2 __attribute__ ((mode (HI)));
Packit Service 82fcde
      signed s4 __attribute__ ((mode (SI)));
Packit Service 82fcde
      signed s8 __attribute__ ((mode (DI)));
Packit Service 82fcde
    } __attribute__((__packed__));
Packit Service 82fcde
Packit Service 82fcde
  union unaligned *u = (union unaligned *) p;
Packit Service 82fcde
  _Unwind_Internal_Ptr result;
Packit Service 82fcde
Packit Service 82fcde
  if (encoding == DW_EH_PE_aligned)
Packit Service 82fcde
    {
Packit Service 82fcde
      _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
Packit Service 82fcde
      a = (a + sizeof (void *) - 1) & - sizeof(void *);
Packit Service 82fcde
      result = *(_Unwind_Internal_Ptr *) a;
Packit Service 82fcde
      p = (const unsigned char *) (a + sizeof (void *));
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      switch (encoding & 0x0f)
Packit Service 82fcde
	{
Packit Service 82fcde
	case DW_EH_PE_absptr:
Packit Service 82fcde
	  result = (_Unwind_Internal_Ptr) u->ptr;
Packit Service 82fcde
	  p += sizeof (void *);
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case DW_EH_PE_uleb128:
Packit Service 82fcde
	  {
Packit Service 82fcde
	    _Unwind_Word tmp;
Packit Service 82fcde
	    p = read_uleb128 (p, &tmp);
Packit Service 82fcde
	    result = (_Unwind_Internal_Ptr) tmp;
Packit Service 82fcde
	  }
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case DW_EH_PE_sleb128:
Packit Service 82fcde
	  {
Packit Service 82fcde
	    _Unwind_Sword tmp;
Packit Service 82fcde
	    p = read_sleb128 (p, &tmp);
Packit Service 82fcde
	    result = (_Unwind_Internal_Ptr) tmp;
Packit Service 82fcde
	  }
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case DW_EH_PE_udata2:
Packit Service 82fcde
	  result = u->u2;
Packit Service 82fcde
	  p += 2;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case DW_EH_PE_udata4:
Packit Service 82fcde
	  result = u->u4;
Packit Service 82fcde
	  p += 4;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case DW_EH_PE_udata8:
Packit Service 82fcde
	  result = u->u8;
Packit Service 82fcde
	  p += 8;
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	case DW_EH_PE_sdata2:
Packit Service 82fcde
	  result = u->s2;
Packit Service 82fcde
	  p += 2;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case DW_EH_PE_sdata4:
Packit Service 82fcde
	  result = u->s4;
Packit Service 82fcde
	  p += 4;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	case DW_EH_PE_sdata8:
Packit Service 82fcde
	  result = u->s8;
Packit Service 82fcde
	  p += 8;
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	default:
Packit Service 82fcde
	  __gxx_abort ();
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      if (result != 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  result += ((encoding & 0x70) == DW_EH_PE_pcrel
Packit Service 82fcde
		     ? (_Unwind_Internal_Ptr) u : base);
Packit Service 82fcde
	  if (encoding & DW_EH_PE_indirect)
Packit Service 82fcde
	    result = *(_Unwind_Internal_Ptr *) result;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  *val = result;
Packit Service 82fcde
  return p;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifndef NO_BASE_OF_ENCODED_VALUE
Packit Service 82fcde
Packit Service 82fcde
/* Like read_encoded_value_with_base, but get the base from the context
Packit Service 82fcde
   rather than providing it directly.  */
Packit Service 82fcde
Packit Service 82fcde
STATIC const unsigned char *
Packit Service 82fcde
read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
Packit Service 82fcde
		    const unsigned char *p, _Unwind_Ptr *val)
Packit Service 82fcde
{
Packit Service 82fcde
  return read_encoded_value_with_base (encoding,
Packit Service 82fcde
		base_of_encoded_value (encoding, context),
Packit Service 82fcde
		p, val);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#endif
Packit Service 82fcde
#endif /* _LIBC */