diff --git a/cxxabi.h b/cxxabi.h
index e021f85..acf9974 100644
--- a/cxxabi.h
+++ b/cxxabi.h
@@ -249,6 +249,10 @@ char* __cxa_demangle(const char* mangled_name,
                      char* buf,
                      size_t* n,
                      int* status);
+
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+size_t __cxa_collect_current_exception_backtrace(void** dest, size_t size);
+#endif
 #ifdef __cplusplus
 } // extern "C"
 } // namespace
diff --git a/exception.cc b/exception.cc
index 15f93ae..c4b15ae 100644
--- a/exception.cc
+++ b/exception.cc
@@ -255,12 +255,20 @@ namespace std
  * various checks may test for equality of the class, which is incorrect.
  */
 static const uint64_t exception_class =
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+    _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_PRIMARY_CLASS;
+#else
 	EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\0');
+#endif
 /**
  * Class used for dependent exceptions.  
  */
 static const uint64_t dependent_exception_class =
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+    _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_DEPENDENT_CLASS;
+#else
 	EXCEPTION_CLASS('G', 'N', 'U', 'C', 'C', '+', '+', '\x01');
+#endif
 /**
  * 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
@@ -605,6 +613,27 @@ static void free_exception(char *e)
 }
 #endif
 
+static constexpr size_t align_to(size_t size, size_t alignment) noexcept {
+    return (size + alignment - 1) / alignment * alignment;
+}
+
+static_assert(align_to(15, 16) == 16);
+static_assert(align_to(16, 16) == 16);
+static_assert(align_to(17, 16) == 32);
+
+static constexpr size_t exception_size = align_to(sizeof(__cxa_exception), 16);
+static constexpr size_t dependent_exception_size = align_to(sizeof(__cxa_dependent_exception), 16);
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+static constexpr size_t backtrace_buffer_size = align_to(sizeof(_Unwind_Backtrace_Buffer), 16);
+
+static_assert(
+    _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_MAGIC_OFFSET ==
+    offsetof(__cxa_exception, unwindHeader) + backtrace_buffer_size - sizeof(_Unwind_Backtrace_Buffer));
+#else
+static constexpr size_t backtrace_buffer_size = 0;
+#endif
+
+
 /**
  * Allocates an exception structure.  Returns a pointer to the space that can
  * be used to store an object of thrown_size bytes.  This function will use an
@@ -613,16 +642,19 @@ static void free_exception(char *e)
  */
 extern "C" void *__cxa_allocate_exception(size_t thrown_size) _LIBCXXRT_NOEXCEPT
 {
-	size_t size = thrown_size + sizeof(__cxa_exception);
+	size_t size = thrown_size + exception_size + backtrace_buffer_size;
 	char *buffer = alloc_or_die(size);
-	return buffer+sizeof(__cxa_exception);
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+	((_Unwind_Backtrace_Buffer *)buffer)->size = 0;
+#endif
+	return buffer + exception_size + backtrace_buffer_size;
 }
 
 extern "C" void *__cxa_allocate_dependent_exception(void)
 {
-	size_t size = sizeof(__cxa_dependent_exception);
+	size_t size = dependent_exception_size + backtrace_buffer_size;
 	char *buffer = alloc_or_die(size);
-	return buffer+sizeof(__cxa_dependent_exception);
+	return buffer + dependent_exception_size + backtrace_buffer_size;
 }
 
 /**
@@ -650,7 +682,8 @@ extern "C" void __cxa_free_exception(void *thrown_exception) _LIBCXXRT_NOEXCEPT
 		}
 	}
 
-	free_exception(reinterpret_cast<char*>(ex));
+	free_exception(
+		reinterpret_cast<char*>(thrown_exception) - exception_size - backtrace_buffer_size);
 }
 
 static void releaseException(__cxa_exception *exception)
@@ -677,7 +710,7 @@ void __cxa_free_dependent_exception(void *thrown_exception)
 	{
 		releaseException(realExceptionFromException(reinterpret_cast<__cxa_exception*>(ex)));
 	}
-	free_exception(reinterpret_cast<char*>(ex));
+	free_exception(reinterpret_cast<char*>(thrown_exception) - dependent_exception_size - backtrace_buffer_size);
 }
 
 /**
@@ -864,6 +897,32 @@ extern "C" void __cxa_decrement_exception_refcount(void* thrown_exception)
 	releaseException(ex);
 }
 
+#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
+static size_t __cxa_collect_backtrace(__cxa_exception* ex, void** dest, size_t size) {
+    if (!ex) {
+        return 0;
+    }
+    if (!isCXXException(ex->unwindHeader.exception_class)) {
+        return 0;
+    }
+    size_t i = 0;
+    if (isDependentException(ex->unwindHeader.exception_class)) {
+        i = __cxa_collect_backtrace(
+                (__cxa_exception *)((__cxa_dependent_exception *)ex)->primaryException - 1, dest, size);
+    }
+    _Unwind_Backtrace_Buffer* backtraceBuffer = (_Unwind_Backtrace_Buffer*)(
+            (char *)(ex + 1) - exception_size - backtrace_buffer_size);
+    for (size_t j = 0; i != size && j != backtraceBuffer->size; ++i, ++j) {
+        dest[i] = backtraceBuffer->backtrace[j];
+    }
+    return i;
+}
+
+extern "C" size_t __cxa_collect_current_exception_backtrace(void** dest, size_t size) {
+    return __cxa_collect_backtrace(__cxa_get_globals()->caughtExceptions, dest, size);
+}
+#endif
+
 /**
  * ABI function.  Rethrows the current exception.  Does not remove the
  * exception from the stack or decrement its handler count - the compiler is