Back to index

glibc  2.9
unwind-pe.h
Go to the documentation of this file.
00001 /* Exception handling and frame unwind runtime interface routines.
00002    Copyright (C) 2001, 2002 Free Software Foundation, Inc.
00003 
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 /* @@@ Really this should be out of line, but this also causes link
00022    compatibility problems with the base ABI.  This is slightly better
00023    than duplicating code, however.  */
00024 
00025 /* If using C++, references to abort have to be qualified with std::.  */
00026 #if __cplusplus
00027 #define __gxx_abort std::abort
00028 #else
00029 #define __gxx_abort abort
00030 #endif
00031 
00032 /* Pointer encodings, from dwarf2.h.  */
00033 #define DW_EH_PE_absptr         0x00
00034 #define DW_EH_PE_omit           0xff
00035 
00036 #define DW_EH_PE_uleb128        0x01
00037 #define DW_EH_PE_udata2         0x02
00038 #define DW_EH_PE_udata4         0x03
00039 #define DW_EH_PE_udata8         0x04
00040 #define DW_EH_PE_sleb128        0x09
00041 #define DW_EH_PE_sdata2         0x0A
00042 #define DW_EH_PE_sdata4         0x0B
00043 #define DW_EH_PE_sdata8         0x0C
00044 #define DW_EH_PE_signed         0x08
00045 
00046 #define DW_EH_PE_pcrel          0x10
00047 #define DW_EH_PE_textrel        0x20
00048 #define DW_EH_PE_datarel        0x30
00049 #define DW_EH_PE_funcrel        0x40
00050 #define DW_EH_PE_aligned        0x50
00051 
00052 #define DW_EH_PE_indirect   0x80
00053 
00054 
00055 #if defined(_LIBC)
00056 
00057 /* Prototypes.  */
00058 extern unsigned int size_of_encoded_value (unsigned char encoding)
00059   attribute_hidden;
00060 
00061 extern const unsigned char *read_encoded_value_with_base
00062   (unsigned char encoding, _Unwind_Ptr base,
00063    const unsigned char *p, _Unwind_Ptr *val)
00064   attribute_hidden;
00065 
00066 extern const unsigned char * read_encoded_value
00067   (struct _Unwind_Context *context, unsigned char encoding,
00068    const unsigned char *p, _Unwind_Ptr *val)
00069   attribute_hidden;
00070 
00071 extern const unsigned char * read_uleb128 (const unsigned char *p,
00072                                       _Unwind_Word *val)
00073   attribute_hidden;
00074 extern const unsigned char * read_sleb128 (const unsigned char *p,
00075                                       _Unwind_Sword *val)
00076   attribute_hidden;
00077 
00078 #endif
00079 #if defined(_LIBC) && defined(_LIBC_DEFINITIONS)
00080 
00081 #ifdef _LIBC
00082 #define STATIC
00083 #else
00084 #define STATIC static
00085 #endif
00086 
00087 /* Given an encoding, return the number of bytes the format occupies.
00088    This is only defined for fixed-size encodings, and so does not
00089    include leb128.  */
00090 
00091 STATIC unsigned int
00092 size_of_encoded_value (unsigned char encoding)
00093 {
00094   if (encoding == DW_EH_PE_omit)
00095     return 0;
00096 
00097   switch (encoding & 0x07)
00098     {
00099     case DW_EH_PE_absptr:
00100       return sizeof (void *);
00101     case DW_EH_PE_udata2:
00102       return 2;
00103     case DW_EH_PE_udata4:
00104       return 4;
00105     case DW_EH_PE_udata8:
00106       return 8;
00107     }
00108   __gxx_abort ();
00109 }
00110 
00111 #ifndef NO_BASE_OF_ENCODED_VALUE
00112 
00113 /* Given an encoding and an _Unwind_Context, return the base to which
00114    the encoding is relative.  This base may then be passed to
00115    read_encoded_value_with_base for use when the _Unwind_Context is
00116    not available.  */
00117 
00118 STATIC _Unwind_Ptr
00119 base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
00120 {
00121   if (encoding == DW_EH_PE_omit)
00122     return 0;
00123 
00124   switch (encoding & 0x70)
00125     {
00126     case DW_EH_PE_absptr:
00127     case DW_EH_PE_pcrel:
00128     case DW_EH_PE_aligned:
00129       return 0;
00130 
00131     case DW_EH_PE_textrel:
00132       return _Unwind_GetTextRelBase (context);
00133     case DW_EH_PE_datarel:
00134       return _Unwind_GetDataRelBase (context);
00135     case DW_EH_PE_funcrel:
00136       return _Unwind_GetRegionStart (context);
00137     }
00138   __gxx_abort ();
00139 }
00140 
00141 #endif
00142 
00143 /* Read an unsigned leb128 value from P, store the value in VAL, return
00144    P incremented past the value.  We assume that a word is large enough to
00145    hold any value so encoded; if it is smaller than a pointer on some target,
00146    pointers should not be leb128 encoded on that target.  */
00147 
00148 STATIC const unsigned char *
00149 read_uleb128 (const unsigned char *p, _Unwind_Word *val)
00150 {
00151   unsigned int shift = 0;
00152   unsigned char byte;
00153   _Unwind_Word result;
00154 
00155   result = 0;
00156   do
00157     {
00158       byte = *p++;
00159       result |= (byte & 0x7f) << shift;
00160       shift += 7;
00161     }
00162   while (byte & 0x80);
00163 
00164   *val = result;
00165   return p;
00166 }
00167 
00168 /* Similar, but read a signed leb128 value.  */
00169 
00170 STATIC const unsigned char *
00171 read_sleb128 (const unsigned char *p, _Unwind_Sword *val)
00172 {
00173   unsigned int shift = 0;
00174   unsigned char byte;
00175   _Unwind_Word result;
00176 
00177   result = 0;
00178   do
00179     {
00180       byte = *p++;
00181       result |= (byte & 0x7f) << shift;
00182       shift += 7;
00183     }
00184   while (byte & 0x80);
00185 
00186   /* Sign-extend a negative value.  */
00187   if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
00188     result |= -(1L << shift);
00189 
00190   *val = (_Unwind_Sword) result;
00191   return p;
00192 }
00193 
00194 /* Load an encoded value from memory at P.  The value is returned in VAL;
00195    The function returns P incremented past the value.  BASE is as given
00196    by base_of_encoded_value for this encoding in the appropriate context.  */
00197 
00198 STATIC const unsigned char *
00199 read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
00200                            const unsigned char *p, _Unwind_Ptr *val)
00201 {
00202   union unaligned
00203     {
00204       void *ptr;
00205       unsigned u2 __attribute__ ((mode (HI)));
00206       unsigned u4 __attribute__ ((mode (SI)));
00207       unsigned u8 __attribute__ ((mode (DI)));
00208       signed s2 __attribute__ ((mode (HI)));
00209       signed s4 __attribute__ ((mode (SI)));
00210       signed s8 __attribute__ ((mode (DI)));
00211     } __attribute__((__packed__));
00212 
00213   union unaligned *u = (union unaligned *) p;
00214   _Unwind_Internal_Ptr result;
00215 
00216   if (encoding == DW_EH_PE_aligned)
00217     {
00218       _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
00219       a = (a + sizeof (void *) - 1) & - sizeof(void *);
00220       result = *(_Unwind_Internal_Ptr *) a;
00221       p = (const unsigned char *) (a + sizeof (void *));
00222     }
00223   else
00224     {
00225       switch (encoding & 0x0f)
00226        {
00227        case DW_EH_PE_absptr:
00228          result = (_Unwind_Internal_Ptr) u->ptr;
00229          p += sizeof (void *);
00230          break;
00231 
00232        case DW_EH_PE_uleb128:
00233          {
00234            _Unwind_Word tmp;
00235            p = read_uleb128 (p, &tmp);
00236            result = (_Unwind_Internal_Ptr) tmp;
00237          }
00238          break;
00239 
00240        case DW_EH_PE_sleb128:
00241          {
00242            _Unwind_Sword tmp;
00243            p = read_sleb128 (p, &tmp);
00244            result = (_Unwind_Internal_Ptr) tmp;
00245          }
00246          break;
00247 
00248        case DW_EH_PE_udata2:
00249          result = u->u2;
00250          p += 2;
00251          break;
00252        case DW_EH_PE_udata4:
00253          result = u->u4;
00254          p += 4;
00255          break;
00256        case DW_EH_PE_udata8:
00257          result = u->u8;
00258          p += 8;
00259          break;
00260 
00261        case DW_EH_PE_sdata2:
00262          result = u->s2;
00263          p += 2;
00264          break;
00265        case DW_EH_PE_sdata4:
00266          result = u->s4;
00267          p += 4;
00268          break;
00269        case DW_EH_PE_sdata8:
00270          result = u->s8;
00271          p += 8;
00272          break;
00273 
00274        default:
00275          __gxx_abort ();
00276        }
00277 
00278       if (result != 0)
00279        {
00280          result += ((encoding & 0x70) == DW_EH_PE_pcrel
00281                    ? (_Unwind_Internal_Ptr) u : base);
00282          if (encoding & DW_EH_PE_indirect)
00283            result = *(_Unwind_Internal_Ptr *) result;
00284        }
00285     }
00286 
00287   *val = result;
00288   return p;
00289 }
00290 
00291 #ifndef NO_BASE_OF_ENCODED_VALUE
00292 
00293 /* Like read_encoded_value_with_base, but get the base from the context
00294    rather than providing it directly.  */
00295 
00296 STATIC const unsigned char *
00297 read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
00298                   const unsigned char *p, _Unwind_Ptr *val)
00299 {
00300   return read_encoded_value_with_base (encoding,
00301               base_of_encoded_value (encoding, context),
00302               p, val);
00303 }
00304 
00305 #endif
00306 #endif /* _LIBC */