svn commit: r227973 -
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4
David Chisnall
theraven at FreeBSD.org
Fri Nov 25 15:48:31 UTC 2011
Author: theraven
Date: Fri Nov 25 15:48:30 2011
New Revision: 227973
URL: http://svn.freebsd.org/changeset/base/227973
Log:
libcxxrt version snapshot created.
Approved by: dim (mentor)
Added:
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/
- copied from r227971, vendor/libcxxrt/dist/
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/unwind-arm.h
- copied unchanged from r227972, vendor/libcxxrt/dist/unwind-arm.h
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/unwind-itanium.h
- copied unchanged from r227972, vendor/libcxxrt/dist/unwind-itanium.h
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/unwind.h
- copied unchanged from r227972, vendor/libcxxrt/dist/unwind.h
Replaced:
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/cxxabi.h
- copied unchanged from r227972, vendor/libcxxrt/dist/cxxabi.h
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/dwarf_eh.h
- copied unchanged from r227972, vendor/libcxxrt/dist/dwarf_eh.h
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/exception.cc
- copied unchanged from r227972, vendor/libcxxrt/dist/exception.cc
vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/guard.cc
- copied unchanged from r227972, vendor/libcxxrt/dist/guard.cc
Copied: vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/cxxabi.h (from r227972, vendor/libcxxrt/dist/cxxabi.h)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/cxxabi.h Fri Nov 25 15:48:30 2011 (r227973, copy of r227972, vendor/libcxxrt/dist/cxxabi.h)
@@ -0,0 +1,219 @@
+#ifndef __CXXABI_H_
+#define __CXXABI_H_
+#include <stdint.h>
+#include "unwind.h"
+namespace std
+{
+ class type_info;
+}
+/*
+ * The cxxabi.h header provides a set of public definitions for types and
+ * functions defined by the Itanium C++ ABI specification. For reference, see
+ * the ABI specification here:
+ *
+ * http://sourcery.mentor.com/public/cxx-abi/abi.html
+ *
+ * All deviations from this specification, unless otherwise noted, are
+ * accidental.
+ */
+
+#ifdef __cplusplus
+namespace __cxxabiv1 {
+extern "C" {
+#endif
+/**
+ * Function type to call when an unexpected exception is encountered.
+ */
+typedef void (*unexpected_handler)();
+/**
+ * Function type to call when an unrecoverable condition is encountered.
+ */
+typedef void (*terminate_handler)();
+
+
+/**
+ * Structure used as a header on thrown exceptions. This is the same layout as
+ * defined by the Itanium ABI spec, so should be interoperable with any other
+ * implementation of this spec, such as GNU libsupc++.
+ *
+ * This structure is allocated when an exception is thrown. Unwinding happens
+ * in two phases, the first looks for a handler and the second installs the
+ * context. This structure stores a cache of the handler location between
+ * phase 1 and phase 2. Unfortunately, cleanup information is not cached, so
+ * must be looked up in both phases. This happens for two reasons. The first
+ * is that we don't know how many frames containing cleanups there will be, and
+ * we should avoid dynamic allocation during unwinding (the exception may be
+ * reporting that we've run out of memory). The second is that finding
+ * cleanups is much cheaper than finding handlers, because we don't have to
+ * look at the type table at all.
+ *
+ * Note: Several fields of this structure have not-very-informative names.
+ * These are taken from the ABI spec and have not been changed to make it
+ * easier for people referring to to the spec while reading this code.
+ */
+struct __cxa_exception
+{
+#if __LP64__
+ /**
+ * Reference count. Used to support the C++11 exception_ptr class. This
+ * is prepended to the structure in 64-bit mode and squeezed in to the
+ * padding left before the 64-bit aligned _Unwind_Exception at the end in
+ * 32-bit mode.
+ *
+ * Note that it is safe to extend this structure at the beginning, rather
+ * than the end, because the public API for creating it returns the address
+ * of the end (where the exception object can be stored).
+ */
+ uintptr_t referenceCount;
+#endif
+ /** Type info for the thrown object. */
+ std::type_info *exceptionType;
+ /** Destructor for the object, if one exists. */
+ void (*exceptionDestructor) (void *);
+ /** Handler called when an exception specification is violated. */
+ unexpected_handler unexpectedHandler;
+ /** Hander called to terminate. */
+ terminate_handler terminateHandler;
+ /**
+ * Next exception in the list. If an exception is thrown inside a catch
+ * block and caught in a nested catch, this points to the exception that
+ * will be handled after the inner catch block completes.
+ */
+ __cxa_exception *nextException;
+ /**
+ * The number of handlers that currently have references to this
+ * exception. The top (non-sign) bit of this is used as a flag to indicate
+ * that the exception is being rethrown, so should not be deleted when its
+ * handler count reaches 0 (which it doesn't with the top bit set).
+ */
+ int handlerCount;
+#ifdef __arm__
+ /**
+ * The ARM EH ABI requires the unwind library to keep track of exceptions
+ * during cleanups. These support nesting, so we need to keep a list of
+ * them.
+ */
+ _Unwind_Exception *nextCleanup;
+ /**
+ * The number of cleanups that are currently being run on this exception.
+ */
+ int cleanupCount;
+#endif
+ /**
+ * The selector value to be returned when installing the catch handler.
+ * Used at the call site to determine which catch() block should execute.
+ * This is found in phase 1 of unwinding then installed in phase 2.
+ */
+ int handlerSwitchValue;
+ /**
+ * The action record for the catch. This is cached during phase 1
+ * unwinding.
+ */
+ const char *actionRecord;
+ /**
+ * Pointer to the language-specific data area (LSDA) for the handler
+ * frame. This is unused in this implementation, but set for ABI
+ * compatibility in case we want to mix code in very weird ways.
+ */
+ const char *languageSpecificData;
+ /** The cached landing pad for the catch handler.*/
+ void *catchTemp;
+ /**
+ * The pointer that will be returned as the pointer to the object. When
+ * throwing a class and catching a virtual superclass (for example), we
+ * need to adjust the thrown pointer to make it all work correctly.
+ */
+ void *adjustedPtr;
+#if !__LP64__
+ /**
+ * Reference count. Used to support the C++11 exception_ptr class. This
+ * is prepended to the structure in 64-bit mode and squeezed in to the
+ * padding left before the 64-bit aligned _Unwind_Exception at the end in
+ * 32-bit mode.
+ *
+ * Note that it is safe to extend this structure at the beginning, rather
+ * than the end, because the public API for creating it returns the address
+ * of the end (where the exception object can be stored)
+ */
+ uintptr_t referenceCount;
+#endif
+ /** The language-agnostic part of the exception header. */
+ _Unwind_Exception unwindHeader;
+};
+
+/**
+ * ABI-specified globals structure. Returned by the __cxa_get_globals()
+ * function and its fast variant. This is a per-thread structure - every
+ * thread will have one lazily allocated.
+ *
+ * This structure is defined by the ABI, so may be used outside of this
+ * library.
+ */
+struct __cxa_eh_globals
+{
+ /**
+ * A linked list of exceptions that are currently caught. There may be
+ * several of these in nested catch() blocks.
+ */
+ __cxa_exception *caughtExceptions;
+ /**
+ * The number of uncaught exceptions.
+ */
+ unsigned int uncaughtExceptions;
+};
+/**
+ * ABI function returning the __cxa_eh_globals structure.
+ */
+__cxa_eh_globals *__cxa_get_globals(void);
+/**
+ * Version of __cxa_get_globals() assuming that __cxa_get_globals() has already
+ * been called at least once by this thread.
+ */
+__cxa_eh_globals *__cxa_get_globals_fast(void);
+
+/**
+ * Throws an exception returned by __cxa_current_primary_exception(). This
+ * exception may have been caught in another thread.
+ */
+void __cxa_rethrow_primary_exception(void* thrown_exception);
+/**
+ * Returns the current exception in a form that can be stored in an
+ * exception_ptr object and then rethrown by a call to
+ * __cxa_rethrow_primary_exception().
+ */
+void *__cxa_current_primary_exception(void);
+/**
+ * Increments the reference count of an exception. Called when an
+ * exception_ptr is copied.
+ */
+void __cxa_increment_exception_refcount(void* thrown_exception);
+/**
+ * Decrements the reference count of an exception. Called when an
+ * exception_ptr is deleted.
+ */
+void __cxa_decrement_exception_refcount(void* thrown_exception);
+/**
+ * Demangles a C++ symbol or type name. The buffer, if non-NULL, must be
+ * allocated with malloc() and must be *n bytes or more long. This function
+ * may call realloc() on the value pointed to by buf, and will return the
+ * length of the string via *n.
+ *
+ * The value pointed to by status is set to one of the following:
+ *
+ * 0: success
+ * -1: memory allocation failure
+ * -2: invalid mangled name
+ * -3: invalid arguments
+ */
+char* __cxa_demangle(const char* mangled_name,
+ char* buf,
+ size_t* n,
+ int* status);
+#ifdef __cplusplus
+} // extern "C"
+} // namespace
+
+namespace abi = __cxxabiv1;
+
+#endif /* __cplusplus */
+#endif /* __CXXABI_H_ */
Copied: vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/dwarf_eh.h (from r227972, vendor/libcxxrt/dist/dwarf_eh.h)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/dwarf_eh.h Fri Nov 25 15:48:30 2011 (r227973, copy of r227972, vendor/libcxxrt/dist/dwarf_eh.h)
@@ -0,0 +1,454 @@
+/**
+ * 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 <assert.h>
+
+// 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 <stdint.h>
+
+/// 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
+{
+ /// 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 (enum dwarf_data_encoding)(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,
+ /// Absolute pointer value
+ DW_EH_PE_absptr = 0x00,
+ /// 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 (enum dwarf_data_relative)(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 |= ((int64_t)-1) << bits;
+ }
+ return (int64_t)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 = (uint64_t)(*(type*)(*data));\
+ *data += sizeof(type);\
+ break;
+ 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;
+ case DW_EH_PE_uleb128:
+ v = read_uleb128(data);
+ break;
+ 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 += (uint64_t)start;
+ break;
+ case DW_EH_PE_textrel:
+ v += (uint64_t)_Unwind_GetTextRelBase(c);
+ break;
+ case DW_EH_PE_datarel:
+ v += (uint64_t)_Unwind_GetDataRelBase(c);
+ break;
+ case DW_EH_PE_funcrel:
+ v += (uint64_t)_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 = (uint64_t)(uintptr_t)*(void**)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 = (dw_eh_ptr_t)(uintptr_t)_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 = (uint64_t)(uintptr_t)lsda.region_start;
+ read_value_with_encoding(context, &data, &v);
+ lsda.landing_pads = (dw_eh_ptr_t)(uintptr_t)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 __arm__
+ lsda.type_table_encoding = (DW_EH_PE_pcrel | DW_EH_PE_indirect);
+#endif
+
+ lsda.callsite_encoding = (enum dwarf_data_encoding)(*(data++));
+
+ // Action table is immediately after the call site table
+ lsda.action_table = data;
+ uintptr_t callsite_size = (uintptr_t)read_uleb128(&data);
+ lsda.action_table = data + callsite_size;
+ // Call site table is immediately after the header
+ lsda.call_site_table = (dw_eh_ptr_t)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 = (unsigned char*)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) \
+ (((uint64_t)a << 56) +\
+ ((uint64_t)b << 48) +\
+ ((uint64_t)c << 40) +\
+ ((uint64_t)d << 32) +\
+ ((uint64_t)e << 24) +\
+ ((uint64_t)f << 16) +\
+ ((uint64_t)g << 8) +\
+ ((uint64_t)h))
+
+#define GENERIC_EXCEPTION_CLASS(e,f,g,h) \
+ ((uint32_t)e << 24) +\
+ ((uint32_t)f << 16) +\
+ ((uint32_t)g << 8) +\
+ ((uint32_t)h)
Copied: vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/exception.cc (from r227972, vendor/libcxxrt/dist/exception.cc)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor/libcxxrt/1be67aa8295314fb794c4e933d9bb7c7c33e0ca4/exception.cc Fri Nov 25 15:48:30 2011 (r227973, copy of r227972, vendor/libcxxrt/dist/exception.cc)
@@ -0,0 +1,1421 @@
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <pthread.h>
+#include "typeinfo.h"
+#include "dwarf_eh.h"
+#include "cxxabi.h"
+
+using namespace ABI_NAMESPACE;
+
+/**
+ * Saves the result of the landing pad that we have found. For ARM, this is
+ * stored in the generic unwind structure, while on other platforms it is
+ * stored in the C++ exception.
+ */
+static void saveLandingPad(struct _Unwind_Context *context,
+ struct _Unwind_Exception *ucb,
+ struct __cxa_exception *ex,
+ int selector,
+ dw_eh_ptr_t landingPad)
+{
+#ifdef __arm__
+ // On ARM, we store the saved exception in the generic part of the structure
+ ucb->barrier_cache.sp = _Unwind_GetGR(context, 13);
+ ucb->barrier_cache.bitpattern[1] = (uint32_t)selector;
+ ucb->barrier_cache.bitpattern[3] = (uint32_t)landingPad;
+#endif
+ // Cache the results for the phase 2 unwind, if we found a handler
+ // and this is not a foreign exception.
+ if (ex)
+ {
+ ex->handlerSwitchValue = selector;
+ ex->catchTemp = landingPad;
+ }
+}
+
+/**
+ * Loads the saved landing pad. Returns 1 on success, 0 on failure.
+ */
+static int loadLandingPad(struct _Unwind_Context *context,
+ struct _Unwind_Exception *ucb,
+ struct __cxa_exception *ex,
+ unsigned long *selector,
+ dw_eh_ptr_t *landingPad)
+{
+#ifdef __arm__
+ *selector = ucb->barrier_cache.bitpattern[1];
+ *landingPad = (dw_eh_ptr_t)ucb->barrier_cache.bitpattern[3];
+ return 1;
+#else
+ if (ex)
+ {
+ *selector = ex->handlerSwitchValue;
+ *landingPad = (dw_eh_ptr_t)ex->catchTemp;
+ return 0;
+ }
+ return 0;
+#endif
+}
+
+static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex,
+ struct _Unwind_Context *context)
+{
+#ifdef __arm__
+ if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; }
+#endif
+ return _URC_CONTINUE_UNWIND;
+}
+
+
+extern "C" void __cxa_free_exception(void *thrown_exception);
+extern "C" void __cxa_free_dependent_exception(void *thrown_exception);
+extern "C" void* __dynamic_cast(const void *sub,
+ const __class_type_info *src,
+ const __class_type_info *dst,
+ ptrdiff_t src2dst_offset);
+
+/**
+ * The type of a handler that has been found.
+ */
+typedef enum
+{
+ /** No handler. */
+ handler_none,
+ /**
+ * A cleanup - the exception will propagate through this frame, but code
+ * must be run when this happens.
+ */
+ handler_cleanup,
+ /**
+ * A catch statement. The exception will not propagate past this frame
+ * (without an explicit rethrow).
+ */
+ handler_catch
+} handler_type;
+
+/**
+ * Per-thread info required by the runtime. We store a single structure
+ * pointer in thread-local storage, because this tends to be a scarce resource
+ * and it's impolite to steal all of it and not leave any for the rest of the
+ * program.
+ *
+ * Instances of this structure are allocated lazily - at most one per thread -
+ * and are destroyed on thread termination.
+ */
+struct __cxa_thread_info
+{
+ /** The termination handler for this thread. */
+ terminate_handler terminateHandler;
+ /** The unexpected exception handler for this thread. */
+ unexpected_handler unexpectedHandler;
+ /**
+ * The number of emergency buffers held by this thread. This is 0 in
+ * normal operation - the emergency buffers are only used when malloc()
+ * fails to return memory for allocating an exception. Threads are not
+ * permitted to hold more than 4 emergency buffers (as per recommendation
+ * in ABI spec [3.3.1]).
+ */
+ int emergencyBuffersHeld;
+ /**
+ * The exception currently running in a cleanup.
+ */
+ _Unwind_Exception *currentCleanup;
+ /**
+ * The public part of this structure, accessible from outside of this
+ * module.
+ */
+ __cxa_eh_globals globals;
+};
+/**
+ * Dependent exception. This
+ */
+struct __cxa_dependent_exception
+{
+#if __LP64__
+ void *primaryException;
+#endif
+ std::type_info *exceptionType;
+ void (*exceptionDestructor) (void *);
+ unexpected_handler unexpectedHandler;
+ terminate_handler terminateHandler;
+ __cxa_exception *nextException;
+ int handlerCount;
+#ifdef __arm__
+ _Unwind_Exception *nextCleanup;
+ int cleanupCount;
+#endif
+ int handlerSwitchValue;
+ const char *actionRecord;
+ const char *languageSpecificData;
+ void *catchTemp;
+ void *adjustedPtr;
+#if !__LP64__
+ void *primaryException;
+#endif
+ _Unwind_Exception unwindHeader;
+};
+
+
+namespace std
+{
+ void unexpected();
+ class exception
+ {
+ public:
+ virtual ~exception() throw();
+ virtual const char* what() const throw();
+ };
+
+}
+
+extern "C" std::type_info *__cxa_current_exception_type();
+
+/**
+ * Class of exceptions to distinguish between this and other exception types.
+ *
+ * The first four characters are the vendor ID. Currently, we use GNUC,
+ * because we aim for ABI-compatibility with the GNU implementation, and
+ * various checks may test for equality of the class, which is incorrect.
+ */
+static const uint64_t exception_class =
+ EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\0');
+/**
+ * Class used for dependent exceptions.
+ */
+static const uint64_t dependent_exception_class =
+ EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\x01');
+/**
+ * The low four bytes of the exception class, indicating that we conform to the
+ * Itanium C++ ABI. This is currently unused, but should be used in the future
+ * if we change our exception class, to allow this library and libsupc++ to be
+ * linked to the same executable and both to interoperate.
+ */
+static const uint32_t abi_exception_class =
+ GENERIC_EXCEPTION_CLASS('C', '+', '+', '\0');
+
+static bool isCXXException(uint64_t cls)
+{
+ return (cls == exception_class) || (cls == dependent_exception_class);
+}
+
+static bool isDependentException(uint64_t cls)
+{
+ return cls == dependent_exception_class;
+}
+
+static __cxa_exception *exceptionFromPointer(void *ex)
+{
+ return (__cxa_exception*)((char*)ex -
+ offsetof(struct __cxa_exception, unwindHeader));
+}
+static __cxa_exception *realExceptionFromException(__cxa_exception *ex)
+{
+ if (!isDependentException(ex->unwindHeader.exception_class)) { return ex; }
+ return ((__cxa_exception*)(((__cxa_dependent_exception*)ex)->primaryException))-1;
+}
+
+
+namespace std
+{
+ // Forward declaration of standard library terminate() function used to
+ // abort execution.
+ void terminate(void);
+}
+
+using namespace ABI_NAMESPACE;
+
+
+
+/** The global termination handler. */
+static terminate_handler terminateHandler = abort;
+/** The global unexpected exception handler. */
+static unexpected_handler unexpectedHandler = std::terminate;
+
+/** Key used for thread-local data. */
+static pthread_key_t eh_key;
+
+
+/**
+ * Cleanup function, allowing foreign exception handlers to correctly destroy
+ * this exception if they catch it.
+ */
+static void exception_cleanup(_Unwind_Reason_Code reason,
+ struct _Unwind_Exception *ex)
+{
+ __cxa_free_exception((void*)ex);
+}
+static void dependent_exception_cleanup(_Unwind_Reason_Code reason,
+ struct _Unwind_Exception *ex)
+{
+
+ __cxa_free_dependent_exception((void*)ex);
+}
+
+/**
+ * Recursively walk a list of exceptions and delete them all in post-order.
+ */
+static void free_exception_list(__cxa_exception *ex)
+{
+ if (0 != ex->nextException)
+ {
+ free_exception_list(ex->nextException);
+ }
+ // __cxa_free_exception() expects to be passed the thrown object, which
+ // immediately follows the exception, not the exception itself
+ __cxa_free_exception(ex+1);
+}
+
+/**
+ * Cleanup function called when a thread exists to make certain that all of the
+ * per-thread data is deleted.
+ */
+static void thread_cleanup(void* thread_info)
+{
+ __cxa_thread_info *info = (__cxa_thread_info*)thread_info;
+ if (info->globals.caughtExceptions)
+ {
+ free_exception_list(info->globals.caughtExceptions);
+ }
+ free(thread_info);
+}
+
+
+/**
+ * Once control used to protect the key creation.
+ */
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+/**
+ * Initialise eh_key.
+ */
+static void init_key(void)
+{
+ pthread_key_create(&eh_key, thread_cleanup);
+}
+
+/**
+ * Returns the thread info structure, creating it if it is not already created.
+ */
+static __cxa_thread_info *thread_info()
+{
+ pthread_once(&once_control, init_key);
+ __cxa_thread_info *info = (__cxa_thread_info*)pthread_getspecific(eh_key);
+ if (0 == info)
+ {
+ info = (__cxa_thread_info*)calloc(1, sizeof(__cxa_thread_info));
+ pthread_setspecific(eh_key, info);
+ }
+ return info;
+}
+/**
+ * Fast version of thread_info(). May fail if thread_info() is not called on
+ * this thread at least once already.
+ */
+static __cxa_thread_info *thread_info_fast()
+{
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list