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