Index: stable/10/contrib/libcxxrt/dwarf_eh.h =================================================================== --- stable/10/contrib/libcxxrt/dwarf_eh.h (revision 279455) +++ stable/10/contrib/libcxxrt/dwarf_eh.h (revision 279456) @@ -1,479 +1,477 @@ /* * Copyright 2010-2011 PathScale, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * dwarf_eh.h - Defines some helper functions for parsing DWARF exception * handling tables. * * This file contains various helper functions that are independent of the * language-specific code. It can be used in any personality function for the * Itanium ABI. */ #include // TODO: Factor out Itanium / ARM differences. We probably want an itanium.h // and arm.h that can be included by this file depending on the target ABI. // _GNU_SOURCE must be defined for unwind.h to expose some of the functions // that we want. If it isn't, then we define it and undefine it to make sure // that it doesn't impact the rest of the program. #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 # include "unwind.h" # undef _GNU_SOURCE #else # include "unwind.h" #endif #include /// Type used for pointers into DWARF data typedef unsigned char *dw_eh_ptr_t; // Flag indicating a signed quantity #define DW_EH_PE_signed 0x08 /// DWARF data encoding types. enum dwarf_data_encoding { /// Absolute pointer value DW_EH_PE_absptr = 0x00, /// Unsigned, little-endian, base 128-encoded (variable length). DW_EH_PE_uleb128 = 0x01, /// Unsigned 16-bit integer. DW_EH_PE_udata2 = 0x02, /// Unsigned 32-bit integer. DW_EH_PE_udata4 = 0x03, /// Unsigned 64-bit integer. DW_EH_PE_udata8 = 0x04, /// Signed, little-endian, base 128-encoded (variable length) DW_EH_PE_sleb128 = DW_EH_PE_uleb128 | DW_EH_PE_signed, /// Signed 16-bit integer. DW_EH_PE_sdata2 = DW_EH_PE_udata2 | DW_EH_PE_signed, /// Signed 32-bit integer. DW_EH_PE_sdata4 = DW_EH_PE_udata4 | DW_EH_PE_signed, /// Signed 32-bit integer. DW_EH_PE_sdata8 = DW_EH_PE_udata8 | DW_EH_PE_signed }; /** * Returns the encoding for a DWARF EH table entry. The encoding is stored in * the low four of an octet. The high four bits store the addressing mode. */ static inline enum dwarf_data_encoding get_encoding(unsigned char x) { return static_cast(x & 0xf); } /** * DWARF addressing mode constants. When reading a pointer value from a DWARF * exception table, you must know how it is stored and what the addressing mode * is. The low four bits tell you the encoding, allowing you to decode a * number. The high four bits tell you the addressing mode, allowing you to * turn that number into an address in memory. */ enum dwarf_data_relative { /// Value is omitted DW_EH_PE_omit = 0xff, /// Value relative to program counter DW_EH_PE_pcrel = 0x10, /// Value relative to the text segment DW_EH_PE_textrel = 0x20, /// Value relative to the data segment DW_EH_PE_datarel = 0x30, /// Value relative to the start of the function DW_EH_PE_funcrel = 0x40, /// Aligned pointer (Not supported yet - are they actually used?) DW_EH_PE_aligned = 0x50, /// Pointer points to address of real value DW_EH_PE_indirect = 0x80 }; /** * Returns the addressing mode component of this encoding. */ static inline enum dwarf_data_relative get_base(unsigned char x) { return static_cast(x & 0x70); } /** * Returns whether an encoding represents an indirect address. */ static int is_indirect(unsigned char x) { return ((x & DW_EH_PE_indirect) == DW_EH_PE_indirect); } /** * Returns the size of a fixed-size encoding. This function will abort if * called with a value that is not a fixed-size encoding. */ static inline int dwarf_size_of_fixed_size_field(unsigned char type) { switch (get_encoding(type)) { default: abort(); case DW_EH_PE_sdata2: case DW_EH_PE_udata2: return 2; case DW_EH_PE_sdata4: case DW_EH_PE_udata4: return 4; case DW_EH_PE_sdata8: case DW_EH_PE_udata8: return 8; case DW_EH_PE_absptr: return sizeof(void*); } } /** * Read an unsigned, little-endian, base-128, DWARF value. Updates *data to * point to the end of the value. Stores the number of bits read in the value * pointed to by b, allowing you to determine the value of the highest bit, and * therefore the sign of a signed value. * * This function is not intended to be called directly. Use read_sleb128() or * read_uleb128() for reading signed and unsigned versions, respectively. */ static uint64_t read_leb128(dw_eh_ptr_t *data, int *b) { uint64_t uleb = 0; unsigned int bit = 0; unsigned char digit = 0; // We have to read at least one octet, and keep reading until we get to one // with the high bit unset do { // This check is a bit too strict - we should also check the highest // bit of the digit. assert(bit < sizeof(uint64_t) * 8); // Get the base 128 digit digit = (**data) & 0x7f; // Add it to the current value uleb += digit << bit; // Increase the shift value bit += 7; // Proceed to the next octet (*data)++; // Terminate when we reach a value that does not have the high bit set // (i.e. which was not modified when we mask it with 0x7f) } while ((*(*data - 1)) != digit); *b = bit; return uleb; } /** * Reads an unsigned little-endian base-128 value starting at the address * pointed to by *data. Updates *data to point to the next byte after the end * of the variable-length value. */ static int64_t read_uleb128(dw_eh_ptr_t *data) { int b; return read_leb128(data, &b); } /** * Reads a signed little-endian base-128 value starting at the address pointed * to by *data. Updates *data to point to the next byte after the end of the * variable-length value. */ static int64_t read_sleb128(dw_eh_ptr_t *data) { int bits; // Read as if it's signed uint64_t uleb = read_leb128(data, &bits); // If the most significant bit read is 1, then we need to sign extend it if ((uleb >> (bits-1)) == 1) { // Sign extend by setting all bits in front of it to 1 uleb |= static_cast(-1) << bits; } return static_cast(uleb); } /** * Reads a value using the specified encoding from the address pointed to by * *data. Updates the value of *data to point to the next byte after the end * of the data. */ static uint64_t read_value(char encoding, dw_eh_ptr_t *data) { enum dwarf_data_encoding type = get_encoding(encoding); - uint64_t v; switch (type) { // Read fixed-length types #define READ(dwarf, type) \ case dwarf:\ - v = static_cast(*reinterpret_cast(*data));\ - *data += sizeof(type);\ - break; + {\ + type t;\ + memcpy(&t, *data, sizeof t);\ + *data += sizeof t;\ + return static_cast(t);\ + } READ(DW_EH_PE_udata2, uint16_t) READ(DW_EH_PE_udata4, uint32_t) READ(DW_EH_PE_udata8, uint64_t) READ(DW_EH_PE_sdata2, int16_t) READ(DW_EH_PE_sdata4, int32_t) READ(DW_EH_PE_sdata8, int64_t) READ(DW_EH_PE_absptr, intptr_t) #undef READ // Read variable-length types case DW_EH_PE_sleb128: - v = read_sleb128(data); - break; + return read_sleb128(data); case DW_EH_PE_uleb128: - v = read_uleb128(data); - break; + return read_uleb128(data); default: abort(); } - - return v; } /** * Resolves an indirect value. This expects an unwind context, an encoding, a * decoded value, and the start of the region as arguments. The returned value * is a pointer to the address identified by the encoded value. * * If the encoding does not specify an indirect value, then this returns v. */ static uint64_t resolve_indirect_value(_Unwind_Context *c, unsigned char encoding, int64_t v, dw_eh_ptr_t start) { switch (get_base(encoding)) { case DW_EH_PE_pcrel: v += reinterpret_cast(start); break; case DW_EH_PE_textrel: v += static_cast(static_cast(_Unwind_GetTextRelBase(c))); break; case DW_EH_PE_datarel: v += static_cast(static_cast(_Unwind_GetDataRelBase(c))); break; case DW_EH_PE_funcrel: v += static_cast(static_cast(_Unwind_GetRegionStart(c))); default: break; } // If this is an indirect value, then it is really the address of the real // value // TODO: Check whether this should really always be a pointer - it seems to // be a GCC extensions, so not properly documented... if (is_indirect(encoding)) { v = static_cast(reinterpret_cast(*reinterpret_cast(v))); } return v; } /** * Reads an encoding and a value, updating *data to point to the next byte. */ static inline void read_value_with_encoding(_Unwind_Context *context, dw_eh_ptr_t *data, uint64_t *out) { dw_eh_ptr_t start = *data; unsigned char encoding = *((*data)++); // If this value is omitted, skip it and don't touch the output value if (encoding == DW_EH_PE_omit) { return; } *out = read_value(encoding, data); *out = resolve_indirect_value(context, encoding, *out, start); } /** * Structure storing a decoded language-specific data area. Use parse_lsda() * to generate an instance of this structure from the address returned by the * generic unwind library. * * You should not need to inspect the fields of this structure directly if you * are just using this header. The structure stores the locations of the * various tables used for unwinding exceptions and is used by the functions * for reading values from these tables. */ struct dwarf_eh_lsda { /// The start of the region. This is a cache of the value returned by /// _Unwind_GetRegionStart(). dw_eh_ptr_t region_start; /// The start of the landing pads table. dw_eh_ptr_t landing_pads; /// The start of the type table. dw_eh_ptr_t type_table; /// The encoding used for entries in the type tables. unsigned char type_table_encoding; /// The location of the call-site table. dw_eh_ptr_t call_site_table; /// The location of the action table. dw_eh_ptr_t action_table; /// The encoding used for entries in the call-site table. unsigned char callsite_encoding; }; /** * Parse the header on the language-specific data area and return a structure * containing the addresses and encodings of the various tables. */ static inline struct dwarf_eh_lsda parse_lsda(_Unwind_Context *context, unsigned char *data) { struct dwarf_eh_lsda lsda; lsda.region_start = reinterpret_cast(_Unwind_GetRegionStart(context)); // If the landing pads are relative to anything other than the start of // this region, find out where. This is @LPStart in the spec, although the // encoding that GCC uses does not quite match the spec. uint64_t v = static_cast(reinterpret_cast(lsda.region_start)); read_value_with_encoding(context, &data, &v); lsda.landing_pads = reinterpret_cast(static_cast(v)); // If there is a type table, find out where it is. This is @TTBase in the // spec. Note: we find whether there is a type table pointer by checking // whether the leading byte is DW_EH_PE_omit (0xff), which is not what the // spec says, but does seem to be how G++ indicates this. lsda.type_table = 0; lsda.type_table_encoding = *data++; if (lsda.type_table_encoding != DW_EH_PE_omit) { v = read_uleb128(&data); dw_eh_ptr_t type_table = data; type_table += v; lsda.type_table = type_table; //lsda.type_table = (uintptr_t*)(data + v); } #if defined(__arm__) && !defined(__ARM_DWARF_EH__) lsda.type_table_encoding = (DW_EH_PE_pcrel | DW_EH_PE_indirect); #endif lsda.callsite_encoding = static_cast(*(data++)); // Action table is immediately after the call site table lsda.action_table = data; uintptr_t callsite_size = static_cast(read_uleb128(&data)); lsda.action_table = data + callsite_size; // Call site table is immediately after the header lsda.call_site_table = static_cast(data); return lsda; } /** * Structure representing an action to be performed while unwinding. This * contains the address that should be unwound to and the action record that * provoked this action. */ struct dwarf_eh_action { /** * The address that this action directs should be the new program counter * value after unwinding. */ dw_eh_ptr_t landing_pad; /// The address of the action record. dw_eh_ptr_t action_record; }; /** * Look up the landing pad that corresponds to the current invoke. * Returns true if record exists. The context is provided by the generic * unwind library and the lsda should be the result of a call to parse_lsda(). * * The action record is returned via the result parameter. */ static bool dwarf_eh_find_callsite(struct _Unwind_Context *context, struct dwarf_eh_lsda *lsda, struct dwarf_eh_action *result) { result->action_record = 0; result->landing_pad = 0; // The current instruction pointer offset within the region uint64_t ip = _Unwind_GetIP(context) - _Unwind_GetRegionStart(context); unsigned char *callsite_table = static_cast(lsda->call_site_table); while (callsite_table <= lsda->action_table) { // Once again, the layout deviates from the spec. uint64_t call_site_start, call_site_size, landing_pad, action; call_site_start = read_value(lsda->callsite_encoding, &callsite_table); call_site_size = read_value(lsda->callsite_encoding, &callsite_table); // Call site entries are sorted, so if we find a call site that's after // the current instruction pointer then there is no action associated // with this call and we should unwind straight through this frame // without doing anything. if (call_site_start > ip) { break; } // Read the address of the landing pad and the action from the call // site table. landing_pad = read_value(lsda->callsite_encoding, &callsite_table); action = read_uleb128(&callsite_table); // We should not include the call_site_start (beginning of the region) // address in the ip range. For each call site: // // address1: call proc // address2: next instruction // // The call stack contains address2 and not address1, address1 can be // at the end of another EH region. if (call_site_start < ip && ip <= call_site_start + call_site_size) { if (action) { // Action records are 1-biased so both no-record and zeroth // record can be stored. result->action_record = lsda->action_table + action - 1; } // No landing pad means keep unwinding. if (landing_pad) { // Landing pad is the offset from the value in the header result->landing_pad = lsda->landing_pads + landing_pad; } return true; } } return false; } /// Defines an exception class from 8 bytes (endian independent) #define EXCEPTION_CLASS(a,b,c,d,e,f,g,h) \ ((static_cast(a) << 56) +\ (static_cast(b) << 48) +\ (static_cast(c) << 40) +\ (static_cast(d) << 32) +\ (static_cast(e) << 24) +\ (static_cast(f) << 16) +\ (static_cast(g) << 8) +\ (static_cast(h))) #define GENERIC_EXCEPTION_CLASS(e,f,g,h) \ (static_cast(e) << 24) +\ (static_cast(f) << 16) +\ (static_cast(g) << 8) +\ (static_cast(h)) Index: stable/10/contrib/libcxxrt/unwind-arm.h =================================================================== --- stable/10/contrib/libcxxrt/unwind-arm.h (revision 279455) +++ stable/10/contrib/libcxxrt/unwind-arm.h (revision 279456) @@ -1,223 +1,225 @@ /* * Copyright 2012 David Chisnall. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * ARM-specific unwind definitions. These are taken from the ARM EHABI * specification. */ typedef enum { _URC_OK = 0, /* operation completed successfully */ _URC_FOREIGN_EXCEPTION_CAUGHT = 1, _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8, _URC_FAILURE = 9, /* unspecified failure of some kind */ _URC_FATAL_PHASE1_ERROR = _URC_FAILURE } _Unwind_Reason_Code; +typedef int _Unwind_Action; + typedef uint32_t _Unwind_State; #ifdef __clang__ static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; #else // GCC fails at knowing what a constant expression is # define _US_VIRTUAL_UNWIND_FRAME 0 # define _US_UNWIND_FRAME_STARTING 1 # define _US_UNWIND_FRAME_RESUME 2 #endif typedef struct _Unwind_Context _Unwind_Context; typedef uint32_t _Unwind_EHT_Header; struct _Unwind_Exception { uint64_t exception_class; void (*exception_cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception *); /* Unwinder cache, private fields for the unwinder's use */ struct { uint32_t reserved1; uint32_t reserved2; uint32_t reserved3; uint32_t reserved4; uint32_t reserved5; /* init reserved1 to 0, then don't touch */ } unwinder_cache; /* Propagation barrier cache (valid after phase 1): */ struct { uint32_t sp; uint32_t bitpattern[5]; } barrier_cache; /* Cleanup cache (preserved over cleanup): */ struct { uint32_t bitpattern[4]; } cleanup_cache; /* Pr cache (for pr's benefit): */ struct { /** function start address */ uint32_t fnstart; /** pointer to EHT entry header word */ _Unwind_EHT_Header *ehtp; /** additional data */ uint32_t additional; uint32_t reserved1; } pr_cache; /** Force alignment of next item to 8-byte boundary */ long long int :0; }; /* Unwinding functions */ _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *ucbp); void _Unwind_Resume(struct _Unwind_Exception *ucbp); void _Unwind_Complete(struct _Unwind_Exception *ucbp); void _Unwind_DeleteException(struct _Unwind_Exception *ucbp); void *_Unwind_GetLanguageSpecificData(struct _Unwind_Context*); typedef enum { _UVRSR_OK = 0, _UVRSR_NOT_IMPLEMENTED = 1, _UVRSR_FAILED = 2 } _Unwind_VRS_Result; typedef enum { _UVRSC_CORE = 0, _UVRSC_VFP = 1, _UVRSC_WMMXD = 3, _UVRSC_WMMXC = 4 } _Unwind_VRS_RegClass; typedef enum { _UVRSD_UINT32 = 0, _UVRSD_VFPX = 1, _UVRSD_UINT64 = 3, _UVRSD_FLOAT = 4, _UVRSD_DOUBLE = 5 } _Unwind_VRS_DataRepresentation; _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep); _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep); /* Return the base-address for data references. */ extern unsigned long _Unwind_GetDataRelBase(struct _Unwind_Context *); /* Return the base-address for text references. */ extern unsigned long _Unwind_GetTextRelBase(struct _Unwind_Context *); extern unsigned long _Unwind_GetRegionStart(struct _Unwind_Context *); typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, void *); extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); extern _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); /** * The next set of functions are compatibility extensions, implementing Itanium * ABI functions on top of ARM ones. */ #define _UA_SEARCH_PHASE 1 #define _UA_CLEANUP_PHASE 2 #define _UA_HANDLER_FRAME 4 #define _UA_FORCE_UNWIND 8 static inline unsigned long _Unwind_GetGR(struct _Unwind_Context *context, int reg) { unsigned long val; _Unwind_VRS_Get(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); return val; } static inline void _Unwind_SetGR(struct _Unwind_Context *context, int reg, unsigned long val) { _Unwind_VRS_Set(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); } static inline unsigned long _Unwind_GetIP(_Unwind_Context *context) { // Low bit store the thumb state - discard it return _Unwind_GetGR(context, 15) & ~1; } static inline void _Unwind_SetIP(_Unwind_Context *context, unsigned long val) { // The lowest bit of the instruction pointer indicates whether we're in // thumb or ARM mode. This is assumed to be fixed throughout a function, // so must be propagated when setting the program counter. unsigned long thumbState = _Unwind_GetGR(context, 15) & 1; _Unwind_SetGR(context, 15, (val | thumbState)); } /** GNU API function that unwinds the frame */ _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*, struct _Unwind_Context*); #define DECLARE_PERSONALITY_FUNCTION(name) \ _Unwind_Reason_Code name(_Unwind_State state,\ struct _Unwind_Exception *exceptionObject,\ struct _Unwind_Context *context); #define BEGIN_PERSONALITY_FUNCTION(name) \ _Unwind_Reason_Code name(_Unwind_State state,\ struct _Unwind_Exception *exceptionObject,\ struct _Unwind_Context *context)\ {\ int version = 1;\ uint64_t exceptionClass = exceptionObject->exception_class;\ int actions;\ switch (state)\ {\ default: return _URC_FAILURE;\ case _US_VIRTUAL_UNWIND_FRAME:\ {\ actions = _UA_SEARCH_PHASE;\ break;\ }\ case _US_UNWIND_FRAME_STARTING:\ {\ actions = _UA_CLEANUP_PHASE;\ if (exceptionObject->barrier_cache.sp == _Unwind_GetGR(context, 13))\ {\ actions |= _UA_HANDLER_FRAME;\ }\ break;\ }\ case _US_UNWIND_FRAME_RESUME:\ {\ return continueUnwinding(exceptionObject, context);\ break;\ }\ }\ _Unwind_SetGR (context, 12, reinterpret_cast(exceptionObject));\ #define CALL_PERSONALITY_FUNCTION(name) name(state,exceptionObject,context) Index: stable/10 =================================================================== --- stable/10 (revision 279455) +++ stable/10 (revision 279456) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r279307,279310 Index: stable/9/contrib/libcxxrt/dwarf_eh.h =================================================================== --- stable/9/contrib/libcxxrt/dwarf_eh.h (revision 279455) +++ stable/9/contrib/libcxxrt/dwarf_eh.h (revision 279456) @@ -1,479 +1,477 @@ /* * Copyright 2010-2011 PathScale, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * dwarf_eh.h - Defines some helper functions for parsing DWARF exception * handling tables. * * This file contains various helper functions that are independent of the * language-specific code. It can be used in any personality function for the * Itanium ABI. */ #include // TODO: Factor out Itanium / ARM differences. We probably want an itanium.h // and arm.h that can be included by this file depending on the target ABI. // _GNU_SOURCE must be defined for unwind.h to expose some of the functions // that we want. If it isn't, then we define it and undefine it to make sure // that it doesn't impact the rest of the program. #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 # include "unwind.h" # undef _GNU_SOURCE #else # include "unwind.h" #endif #include /// Type used for pointers into DWARF data typedef unsigned char *dw_eh_ptr_t; // Flag indicating a signed quantity #define DW_EH_PE_signed 0x08 /// DWARF data encoding types. enum dwarf_data_encoding { /// Absolute pointer value DW_EH_PE_absptr = 0x00, /// Unsigned, little-endian, base 128-encoded (variable length). DW_EH_PE_uleb128 = 0x01, /// Unsigned 16-bit integer. DW_EH_PE_udata2 = 0x02, /// Unsigned 32-bit integer. DW_EH_PE_udata4 = 0x03, /// Unsigned 64-bit integer. DW_EH_PE_udata8 = 0x04, /// Signed, little-endian, base 128-encoded (variable length) DW_EH_PE_sleb128 = DW_EH_PE_uleb128 | DW_EH_PE_signed, /// Signed 16-bit integer. DW_EH_PE_sdata2 = DW_EH_PE_udata2 | DW_EH_PE_signed, /// Signed 32-bit integer. DW_EH_PE_sdata4 = DW_EH_PE_udata4 | DW_EH_PE_signed, /// Signed 32-bit integer. DW_EH_PE_sdata8 = DW_EH_PE_udata8 | DW_EH_PE_signed }; /** * Returns the encoding for a DWARF EH table entry. The encoding is stored in * the low four of an octet. The high four bits store the addressing mode. */ static inline enum dwarf_data_encoding get_encoding(unsigned char x) { return static_cast(x & 0xf); } /** * DWARF addressing mode constants. When reading a pointer value from a DWARF * exception table, you must know how it is stored and what the addressing mode * is. The low four bits tell you the encoding, allowing you to decode a * number. The high four bits tell you the addressing mode, allowing you to * turn that number into an address in memory. */ enum dwarf_data_relative { /// Value is omitted DW_EH_PE_omit = 0xff, /// Value relative to program counter DW_EH_PE_pcrel = 0x10, /// Value relative to the text segment DW_EH_PE_textrel = 0x20, /// Value relative to the data segment DW_EH_PE_datarel = 0x30, /// Value relative to the start of the function DW_EH_PE_funcrel = 0x40, /// Aligned pointer (Not supported yet - are they actually used?) DW_EH_PE_aligned = 0x50, /// Pointer points to address of real value DW_EH_PE_indirect = 0x80 }; /** * Returns the addressing mode component of this encoding. */ static inline enum dwarf_data_relative get_base(unsigned char x) { return static_cast(x & 0x70); } /** * Returns whether an encoding represents an indirect address. */ static int is_indirect(unsigned char x) { return ((x & DW_EH_PE_indirect) == DW_EH_PE_indirect); } /** * Returns the size of a fixed-size encoding. This function will abort if * called with a value that is not a fixed-size encoding. */ static inline int dwarf_size_of_fixed_size_field(unsigned char type) { switch (get_encoding(type)) { default: abort(); case DW_EH_PE_sdata2: case DW_EH_PE_udata2: return 2; case DW_EH_PE_sdata4: case DW_EH_PE_udata4: return 4; case DW_EH_PE_sdata8: case DW_EH_PE_udata8: return 8; case DW_EH_PE_absptr: return sizeof(void*); } } /** * Read an unsigned, little-endian, base-128, DWARF value. Updates *data to * point to the end of the value. Stores the number of bits read in the value * pointed to by b, allowing you to determine the value of the highest bit, and * therefore the sign of a signed value. * * This function is not intended to be called directly. Use read_sleb128() or * read_uleb128() for reading signed and unsigned versions, respectively. */ static uint64_t read_leb128(dw_eh_ptr_t *data, int *b) { uint64_t uleb = 0; unsigned int bit = 0; unsigned char digit = 0; // We have to read at least one octet, and keep reading until we get to one // with the high bit unset do { // This check is a bit too strict - we should also check the highest // bit of the digit. assert(bit < sizeof(uint64_t) * 8); // Get the base 128 digit digit = (**data) & 0x7f; // Add it to the current value uleb += digit << bit; // Increase the shift value bit += 7; // Proceed to the next octet (*data)++; // Terminate when we reach a value that does not have the high bit set // (i.e. which was not modified when we mask it with 0x7f) } while ((*(*data - 1)) != digit); *b = bit; return uleb; } /** * Reads an unsigned little-endian base-128 value starting at the address * pointed to by *data. Updates *data to point to the next byte after the end * of the variable-length value. */ static int64_t read_uleb128(dw_eh_ptr_t *data) { int b; return read_leb128(data, &b); } /** * Reads a signed little-endian base-128 value starting at the address pointed * to by *data. Updates *data to point to the next byte after the end of the * variable-length value. */ static int64_t read_sleb128(dw_eh_ptr_t *data) { int bits; // Read as if it's signed uint64_t uleb = read_leb128(data, &bits); // If the most significant bit read is 1, then we need to sign extend it if ((uleb >> (bits-1)) == 1) { // Sign extend by setting all bits in front of it to 1 uleb |= static_cast(-1) << bits; } return static_cast(uleb); } /** * Reads a value using the specified encoding from the address pointed to by * *data. Updates the value of *data to point to the next byte after the end * of the data. */ static uint64_t read_value(char encoding, dw_eh_ptr_t *data) { enum dwarf_data_encoding type = get_encoding(encoding); - uint64_t v; switch (type) { // Read fixed-length types #define READ(dwarf, type) \ case dwarf:\ - v = static_cast(*reinterpret_cast(*data));\ - *data += sizeof(type);\ - break; + {\ + type t;\ + memcpy(&t, *data, sizeof t);\ + *data += sizeof t;\ + return static_cast(t);\ + } READ(DW_EH_PE_udata2, uint16_t) READ(DW_EH_PE_udata4, uint32_t) READ(DW_EH_PE_udata8, uint64_t) READ(DW_EH_PE_sdata2, int16_t) READ(DW_EH_PE_sdata4, int32_t) READ(DW_EH_PE_sdata8, int64_t) READ(DW_EH_PE_absptr, intptr_t) #undef READ // Read variable-length types case DW_EH_PE_sleb128: - v = read_sleb128(data); - break; + return read_sleb128(data); case DW_EH_PE_uleb128: - v = read_uleb128(data); - break; + return read_uleb128(data); default: abort(); } - - return v; } /** * Resolves an indirect value. This expects an unwind context, an encoding, a * decoded value, and the start of the region as arguments. The returned value * is a pointer to the address identified by the encoded value. * * If the encoding does not specify an indirect value, then this returns v. */ static uint64_t resolve_indirect_value(_Unwind_Context *c, unsigned char encoding, int64_t v, dw_eh_ptr_t start) { switch (get_base(encoding)) { case DW_EH_PE_pcrel: v += reinterpret_cast(start); break; case DW_EH_PE_textrel: v += static_cast(static_cast(_Unwind_GetTextRelBase(c))); break; case DW_EH_PE_datarel: v += static_cast(static_cast(_Unwind_GetDataRelBase(c))); break; case DW_EH_PE_funcrel: v += static_cast(static_cast(_Unwind_GetRegionStart(c))); default: break; } // If this is an indirect value, then it is really the address of the real // value // TODO: Check whether this should really always be a pointer - it seems to // be a GCC extensions, so not properly documented... if (is_indirect(encoding)) { v = static_cast(reinterpret_cast(*reinterpret_cast(v))); } return v; } /** * Reads an encoding and a value, updating *data to point to the next byte. */ static inline void read_value_with_encoding(_Unwind_Context *context, dw_eh_ptr_t *data, uint64_t *out) { dw_eh_ptr_t start = *data; unsigned char encoding = *((*data)++); // If this value is omitted, skip it and don't touch the output value if (encoding == DW_EH_PE_omit) { return; } *out = read_value(encoding, data); *out = resolve_indirect_value(context, encoding, *out, start); } /** * Structure storing a decoded language-specific data area. Use parse_lsda() * to generate an instance of this structure from the address returned by the * generic unwind library. * * You should not need to inspect the fields of this structure directly if you * are just using this header. The structure stores the locations of the * various tables used for unwinding exceptions and is used by the functions * for reading values from these tables. */ struct dwarf_eh_lsda { /// The start of the region. This is a cache of the value returned by /// _Unwind_GetRegionStart(). dw_eh_ptr_t region_start; /// The start of the landing pads table. dw_eh_ptr_t landing_pads; /// The start of the type table. dw_eh_ptr_t type_table; /// The encoding used for entries in the type tables. unsigned char type_table_encoding; /// The location of the call-site table. dw_eh_ptr_t call_site_table; /// The location of the action table. dw_eh_ptr_t action_table; /// The encoding used for entries in the call-site table. unsigned char callsite_encoding; }; /** * Parse the header on the language-specific data area and return a structure * containing the addresses and encodings of the various tables. */ static inline struct dwarf_eh_lsda parse_lsda(_Unwind_Context *context, unsigned char *data) { struct dwarf_eh_lsda lsda; lsda.region_start = reinterpret_cast(_Unwind_GetRegionStart(context)); // If the landing pads are relative to anything other than the start of // this region, find out where. This is @LPStart in the spec, although the // encoding that GCC uses does not quite match the spec. uint64_t v = static_cast(reinterpret_cast(lsda.region_start)); read_value_with_encoding(context, &data, &v); lsda.landing_pads = reinterpret_cast(static_cast(v)); // If there is a type table, find out where it is. This is @TTBase in the // spec. Note: we find whether there is a type table pointer by checking // whether the leading byte is DW_EH_PE_omit (0xff), which is not what the // spec says, but does seem to be how G++ indicates this. lsda.type_table = 0; lsda.type_table_encoding = *data++; if (lsda.type_table_encoding != DW_EH_PE_omit) { v = read_uleb128(&data); dw_eh_ptr_t type_table = data; type_table += v; lsda.type_table = type_table; //lsda.type_table = (uintptr_t*)(data + v); } #if defined(__arm__) && !defined(__ARM_DWARF_EH__) lsda.type_table_encoding = (DW_EH_PE_pcrel | DW_EH_PE_indirect); #endif lsda.callsite_encoding = static_cast(*(data++)); // Action table is immediately after the call site table lsda.action_table = data; uintptr_t callsite_size = static_cast(read_uleb128(&data)); lsda.action_table = data + callsite_size; // Call site table is immediately after the header lsda.call_site_table = static_cast(data); return lsda; } /** * Structure representing an action to be performed while unwinding. This * contains the address that should be unwound to and the action record that * provoked this action. */ struct dwarf_eh_action { /** * The address that this action directs should be the new program counter * value after unwinding. */ dw_eh_ptr_t landing_pad; /// The address of the action record. dw_eh_ptr_t action_record; }; /** * Look up the landing pad that corresponds to the current invoke. * Returns true if record exists. The context is provided by the generic * unwind library and the lsda should be the result of a call to parse_lsda(). * * The action record is returned via the result parameter. */ static bool dwarf_eh_find_callsite(struct _Unwind_Context *context, struct dwarf_eh_lsda *lsda, struct dwarf_eh_action *result) { result->action_record = 0; result->landing_pad = 0; // The current instruction pointer offset within the region uint64_t ip = _Unwind_GetIP(context) - _Unwind_GetRegionStart(context); unsigned char *callsite_table = static_cast(lsda->call_site_table); while (callsite_table <= lsda->action_table) { // Once again, the layout deviates from the spec. uint64_t call_site_start, call_site_size, landing_pad, action; call_site_start = read_value(lsda->callsite_encoding, &callsite_table); call_site_size = read_value(lsda->callsite_encoding, &callsite_table); // Call site entries are sorted, so if we find a call site that's after // the current instruction pointer then there is no action associated // with this call and we should unwind straight through this frame // without doing anything. if (call_site_start > ip) { break; } // Read the address of the landing pad and the action from the call // site table. landing_pad = read_value(lsda->callsite_encoding, &callsite_table); action = read_uleb128(&callsite_table); // We should not include the call_site_start (beginning of the region) // address in the ip range. For each call site: // // address1: call proc // address2: next instruction // // The call stack contains address2 and not address1, address1 can be // at the end of another EH region. if (call_site_start < ip && ip <= call_site_start + call_site_size) { if (action) { // Action records are 1-biased so both no-record and zeroth // record can be stored. result->action_record = lsda->action_table + action - 1; } // No landing pad means keep unwinding. if (landing_pad) { // Landing pad is the offset from the value in the header result->landing_pad = lsda->landing_pads + landing_pad; } return true; } } return false; } /// Defines an exception class from 8 bytes (endian independent) #define EXCEPTION_CLASS(a,b,c,d,e,f,g,h) \ ((static_cast(a) << 56) +\ (static_cast(b) << 48) +\ (static_cast(c) << 40) +\ (static_cast(d) << 32) +\ (static_cast(e) << 24) +\ (static_cast(f) << 16) +\ (static_cast(g) << 8) +\ (static_cast(h))) #define GENERIC_EXCEPTION_CLASS(e,f,g,h) \ (static_cast(e) << 24) +\ (static_cast(f) << 16) +\ (static_cast(g) << 8) +\ (static_cast(h)) Index: stable/9/contrib/libcxxrt/unwind-arm.h =================================================================== --- stable/9/contrib/libcxxrt/unwind-arm.h (revision 279455) +++ stable/9/contrib/libcxxrt/unwind-arm.h (revision 279456) @@ -1,223 +1,225 @@ /* * Copyright 2012 David Chisnall. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * ARM-specific unwind definitions. These are taken from the ARM EHABI * specification. */ typedef enum { _URC_OK = 0, /* operation completed successfully */ _URC_FOREIGN_EXCEPTION_CAUGHT = 1, _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8, _URC_FAILURE = 9, /* unspecified failure of some kind */ _URC_FATAL_PHASE1_ERROR = _URC_FAILURE } _Unwind_Reason_Code; +typedef int _Unwind_Action; + typedef uint32_t _Unwind_State; #ifdef __clang__ static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; #else // GCC fails at knowing what a constant expression is # define _US_VIRTUAL_UNWIND_FRAME 0 # define _US_UNWIND_FRAME_STARTING 1 # define _US_UNWIND_FRAME_RESUME 2 #endif typedef struct _Unwind_Context _Unwind_Context; typedef uint32_t _Unwind_EHT_Header; struct _Unwind_Exception { uint64_t exception_class; void (*exception_cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception *); /* Unwinder cache, private fields for the unwinder's use */ struct { uint32_t reserved1; uint32_t reserved2; uint32_t reserved3; uint32_t reserved4; uint32_t reserved5; /* init reserved1 to 0, then don't touch */ } unwinder_cache; /* Propagation barrier cache (valid after phase 1): */ struct { uint32_t sp; uint32_t bitpattern[5]; } barrier_cache; /* Cleanup cache (preserved over cleanup): */ struct { uint32_t bitpattern[4]; } cleanup_cache; /* Pr cache (for pr's benefit): */ struct { /** function start address */ uint32_t fnstart; /** pointer to EHT entry header word */ _Unwind_EHT_Header *ehtp; /** additional data */ uint32_t additional; uint32_t reserved1; } pr_cache; /** Force alignment of next item to 8-byte boundary */ long long int :0; }; /* Unwinding functions */ _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *ucbp); void _Unwind_Resume(struct _Unwind_Exception *ucbp); void _Unwind_Complete(struct _Unwind_Exception *ucbp); void _Unwind_DeleteException(struct _Unwind_Exception *ucbp); void *_Unwind_GetLanguageSpecificData(struct _Unwind_Context*); typedef enum { _UVRSR_OK = 0, _UVRSR_NOT_IMPLEMENTED = 1, _UVRSR_FAILED = 2 } _Unwind_VRS_Result; typedef enum { _UVRSC_CORE = 0, _UVRSC_VFP = 1, _UVRSC_WMMXD = 3, _UVRSC_WMMXC = 4 } _Unwind_VRS_RegClass; typedef enum { _UVRSD_UINT32 = 0, _UVRSD_VFPX = 1, _UVRSD_UINT64 = 3, _UVRSD_FLOAT = 4, _UVRSD_DOUBLE = 5 } _Unwind_VRS_DataRepresentation; _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep); _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep); /* Return the base-address for data references. */ extern unsigned long _Unwind_GetDataRelBase(struct _Unwind_Context *); /* Return the base-address for text references. */ extern unsigned long _Unwind_GetTextRelBase(struct _Unwind_Context *); extern unsigned long _Unwind_GetRegionStart(struct _Unwind_Context *); typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, void *); extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); extern _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); /** * The next set of functions are compatibility extensions, implementing Itanium * ABI functions on top of ARM ones. */ #define _UA_SEARCH_PHASE 1 #define _UA_CLEANUP_PHASE 2 #define _UA_HANDLER_FRAME 4 #define _UA_FORCE_UNWIND 8 static inline unsigned long _Unwind_GetGR(struct _Unwind_Context *context, int reg) { unsigned long val; _Unwind_VRS_Get(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); return val; } static inline void _Unwind_SetGR(struct _Unwind_Context *context, int reg, unsigned long val) { _Unwind_VRS_Set(context, _UVRSC_CORE, reg, _UVRSD_UINT32, &val); } static inline unsigned long _Unwind_GetIP(_Unwind_Context *context) { // Low bit store the thumb state - discard it return _Unwind_GetGR(context, 15) & ~1; } static inline void _Unwind_SetIP(_Unwind_Context *context, unsigned long val) { // The lowest bit of the instruction pointer indicates whether we're in // thumb or ARM mode. This is assumed to be fixed throughout a function, // so must be propagated when setting the program counter. unsigned long thumbState = _Unwind_GetGR(context, 15) & 1; _Unwind_SetGR(context, 15, (val | thumbState)); } /** GNU API function that unwinds the frame */ _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception*, struct _Unwind_Context*); #define DECLARE_PERSONALITY_FUNCTION(name) \ _Unwind_Reason_Code name(_Unwind_State state,\ struct _Unwind_Exception *exceptionObject,\ struct _Unwind_Context *context); #define BEGIN_PERSONALITY_FUNCTION(name) \ _Unwind_Reason_Code name(_Unwind_State state,\ struct _Unwind_Exception *exceptionObject,\ struct _Unwind_Context *context)\ {\ int version = 1;\ uint64_t exceptionClass = exceptionObject->exception_class;\ int actions;\ switch (state)\ {\ default: return _URC_FAILURE;\ case _US_VIRTUAL_UNWIND_FRAME:\ {\ actions = _UA_SEARCH_PHASE;\ break;\ }\ case _US_UNWIND_FRAME_STARTING:\ {\ actions = _UA_CLEANUP_PHASE;\ if (exceptionObject->barrier_cache.sp == _Unwind_GetGR(context, 13))\ {\ actions |= _UA_HANDLER_FRAME;\ }\ break;\ }\ case _US_UNWIND_FRAME_RESUME:\ {\ return continueUnwinding(exceptionObject, context);\ break;\ }\ }\ _Unwind_SetGR (context, 12, reinterpret_cast(exceptionObject));\ #define CALL_PERSONALITY_FUNCTION(name) name(state,exceptionObject,context) Index: stable/9/contrib/libcxxrt =================================================================== --- stable/9/contrib/libcxxrt (revision 279455) +++ stable/9/contrib/libcxxrt (revision 279456) Property changes on: stable/9/contrib/libcxxrt ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/contrib/libcxxrt:r279307,279310