unwind-pe.h revision 169689
150472Speter/* Exception handling and frame unwind runtime interface routines. 237Srgrimes Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 378822Snik 450203Srgrimes This file is part of GCC. 537Srgrimes 639161Sobrien GCC is free software; you can redistribute it and/or modify it 739490Sobrien under the terms of the GNU General Public License as published by 88571Srgrimes the Free Software Foundation; either version 2, or (at your option) 92878Srgrimes any later version. 1072515Sru 1172515Sru In addition to the permissions in the GNU General Public License, the 128571Srgrimes Free Software Foundation gives you unlimited permission to link the 132878Srgrimes compiled version of this file into combinations with other programs, 148571Srgrimes and to distribute those combinations without any restriction coming 158571Srgrimes from the use of this file. (The General Public License restrictions 1672515Sru do apply in other respects; for example, they cover modification of 172878Srgrimes the file, and distribution when not linked into a combined 1872515Sru executable.) 19155345Srwatson 20155197Srwatson GCC is distributed in the hope that it will be useful, but WITHOUT 21155197Srwatson ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 22244398Srwatson or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 23244398Srwatson License for more details. 24244398Srwatson 25244398Srwatson You should have received a copy of the GNU General Public License 26155345Srwatson along with GCC; see the file COPYING. If not, write to the Free 2772515Sru Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 282878Srgrimes 02110-1301, USA. */ 29219820Sjeff 30219820Sjeff/* @@@ Really this should be out of line, but this also causes link 3172515Sru compatibility problems with the base ABI. This is slightly better 322878Srgrimes than duplicating code, however. */ 3372515Sru 3472515Sru#ifndef GCC_UNWIND_PE_H 352878Srgrimes#define GCC_UNWIND_PE_H 362878Srgrimes 3772515Sru/* If using C++, references to abort have to be qualified with std::. */ 3872515Sru#if __cplusplus 3972515Sru#define __gxx_abort std::abort 4045173Sasami#else 41200054Scperciva#define __gxx_abort abort 42161748Scperciva#endif 4386601Sru 4485220Sdarrenr/* Pointer encodings, from dwarf2.h. */ 4572515Sru#define DW_EH_PE_absptr 0x00 4672515Sru#define DW_EH_PE_omit 0xff 47124753Seivind 48124753Seivind#define DW_EH_PE_uleb128 0x01 49148871Scperciva#define DW_EH_PE_udata2 0x02 50148871Scperciva#define DW_EH_PE_udata4 0x03 512878Srgrimes#define DW_EH_PE_udata8 0x04 52123051Sru#define DW_EH_PE_sleb128 0x09 5398699Sdes#define DW_EH_PE_sdata2 0x0A 54123051Sru#define DW_EH_PE_sdata4 0x0B 55106403Smarkm#define DW_EH_PE_sdata8 0x0C 5685484Sru#define DW_EH_PE_signed 0x08 5780516Smarkm 5839490Sobrien#define DW_EH_PE_pcrel 0x10 592878Srgrimes#define DW_EH_PE_textrel 0x20 6086601Sru#define DW_EH_PE_datarel 0x30 612878Srgrimes#define DW_EH_PE_funcrel 0x40 6212388Sache#define DW_EH_PE_aligned 0x50 632878Srgrimes 64136552Sru#define DW_EH_PE_indirect 0x80 65135875Sdougb 6639490Sobrien 672878Srgrimes#ifndef NO_SIZE_OF_ENCODED_VALUE 6839490Sobrien 6982191Skuriyama/* Given an encoding, return the number of bytes the format occupies. 7082191Skuriyama This is only defined for fixed-size encodings, and so does not 7185848Scjc include leb128. */ 7285916Scjc 73212411Sbschmidtstatic unsigned int 74212411Sbschmidtsize_of_encoded_value (unsigned char encoding) 752878Srgrimes{ 7686601Sru if (encoding == DW_EH_PE_omit) 772878Srgrimes return 0; 7872515Sru 7986601Sru switch (encoding & 0x07) 802878Srgrimes { 8172515Sru case DW_EH_PE_absptr: 8241855Speter return sizeof (void *); 832878Srgrimes case DW_EH_PE_udata2: 8441855Speter return 2; 852878Srgrimes case DW_EH_PE_udata4: 8650296Srgrimes return 4; 8750296Srgrimes case DW_EH_PE_udata8: 8841855Speter return 8; 8950296Srgrimes } 9050296Srgrimes __gxx_abort (); 912878Srgrimes} 9286601Sru 932878Srgrimes#endif 9472515Sru 9572515Sru#ifndef NO_BASE_OF_ENCODED_VALUE 968571Srgrimes 972878Srgrimes/* Given an encoding and an _Unwind_Context, return the base to which 9841855Speter the encoding is relative. This base may then be passed to 998571Srgrimes read_encoded_value_with_base for use when the _Unwind_Context is 100949Snate not available. */ 101 102static _Unwind_Ptr 103base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context) 104{ 105 if (encoding == DW_EH_PE_omit) 106 return 0; 107 108 switch (encoding & 0x70) 109 { 110 case DW_EH_PE_absptr: 111 case DW_EH_PE_pcrel: 112 case DW_EH_PE_aligned: 113 return 0; 114 115 case DW_EH_PE_textrel: 116 return _Unwind_GetTextRelBase (context); 117 case DW_EH_PE_datarel: 118 return _Unwind_GetDataRelBase (context); 119 case DW_EH_PE_funcrel: 120 return _Unwind_GetRegionStart (context); 121 } 122 __gxx_abort (); 123} 124 125#endif 126 127/* Read an unsigned leb128 value from P, store the value in VAL, return 128 P incremented past the value. We assume that a word is large enough to 129 hold any value so encoded; if it is smaller than a pointer on some target, 130 pointers should not be leb128 encoded on that target. */ 131 132static const unsigned char * 133read_uleb128 (const unsigned char *p, _Unwind_Word *val) 134{ 135 unsigned int shift = 0; 136 unsigned char byte; 137 _Unwind_Word result; 138 139 result = 0; 140 do 141 { 142 byte = *p++; 143 result |= ((_Unwind_Word)byte & 0x7f) << shift; 144 shift += 7; 145 } 146 while (byte & 0x80); 147 148 *val = result; 149 return p; 150} 151 152/* Similar, but read a signed leb128 value. */ 153 154static const unsigned char * 155read_sleb128 (const unsigned char *p, _Unwind_Sword *val) 156{ 157 unsigned int shift = 0; 158 unsigned char byte; 159 _Unwind_Word result; 160 161 result = 0; 162 do 163 { 164 byte = *p++; 165 result |= ((_Unwind_Word)byte & 0x7f) << shift; 166 shift += 7; 167 } 168 while (byte & 0x80); 169 170 /* Sign-extend a negative value. */ 171 if (shift < 8 * sizeof(result) && (byte & 0x40) != 0) 172 result |= -(((_Unwind_Word)1L) << shift); 173 174 *val = (_Unwind_Sword) result; 175 return p; 176} 177 178/* Load an encoded value from memory at P. The value is returned in VAL; 179 The function returns P incremented past the value. BASE is as given 180 by base_of_encoded_value for this encoding in the appropriate context. */ 181 182static const unsigned char * 183read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, 184 const unsigned char *p, _Unwind_Ptr *val) 185{ 186 union unaligned 187 { 188 void *ptr; 189 unsigned u2 __attribute__ ((mode (HI))); 190 unsigned u4 __attribute__ ((mode (SI))); 191 unsigned u8 __attribute__ ((mode (DI))); 192 signed s2 __attribute__ ((mode (HI))); 193 signed s4 __attribute__ ((mode (SI))); 194 signed s8 __attribute__ ((mode (DI))); 195 } __attribute__((__packed__)); 196 197 const union unaligned *u = (const union unaligned *) p; 198 _Unwind_Internal_Ptr result; 199 200 if (encoding == DW_EH_PE_aligned) 201 { 202 _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p; 203 a = (a + sizeof (void *) - 1) & - sizeof(void *); 204 result = *(_Unwind_Internal_Ptr *) a; 205 p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *)); 206 } 207 else 208 { 209 switch (encoding & 0x0f) 210 { 211 case DW_EH_PE_absptr: 212 result = (_Unwind_Internal_Ptr) u->ptr; 213 p += sizeof (void *); 214 break; 215 216 case DW_EH_PE_uleb128: 217 { 218 _Unwind_Word tmp; 219 p = read_uleb128 (p, &tmp); 220 result = (_Unwind_Internal_Ptr) tmp; 221 } 222 break; 223 224 case DW_EH_PE_sleb128: 225 { 226 _Unwind_Sword tmp; 227 p = read_sleb128 (p, &tmp); 228 result = (_Unwind_Internal_Ptr) tmp; 229 } 230 break; 231 232 case DW_EH_PE_udata2: 233 result = u->u2; 234 p += 2; 235 break; 236 case DW_EH_PE_udata4: 237 result = u->u4; 238 p += 4; 239 break; 240 case DW_EH_PE_udata8: 241 result = u->u8; 242 p += 8; 243 break; 244 245 case DW_EH_PE_sdata2: 246 result = u->s2; 247 p += 2; 248 break; 249 case DW_EH_PE_sdata4: 250 result = u->s4; 251 p += 4; 252 break; 253 case DW_EH_PE_sdata8: 254 result = u->s8; 255 p += 8; 256 break; 257 258 default: 259 __gxx_abort (); 260 } 261 262 if (result != 0) 263 { 264 result += ((encoding & 0x70) == DW_EH_PE_pcrel 265 ? (_Unwind_Internal_Ptr) u : base); 266 if (encoding & DW_EH_PE_indirect) 267 result = *(_Unwind_Internal_Ptr *) result; 268 } 269 } 270 271 *val = result; 272 return p; 273} 274 275#ifndef NO_BASE_OF_ENCODED_VALUE 276 277/* Like read_encoded_value_with_base, but get the base from the context 278 rather than providing it directly. */ 279 280static inline const unsigned char * 281read_encoded_value (struct _Unwind_Context *context, unsigned char encoding, 282 const unsigned char *p, _Unwind_Ptr *val) 283{ 284 return read_encoded_value_with_base (encoding, 285 base_of_encoded_value (encoding, context), 286 p, val); 287} 288 289#endif 290 291#endif /* unwind-pe.h */ 292