Merge "Correct the size of _Unwind_Exception."
diff --git a/sources/cxx-stl/gabi++/include/unwind-itanium.h b/sources/cxx-stl/gabi++/include/unwind-itanium.h
index bd7a4b2..717cc56 100644
--- a/sources/cxx-stl/gabi++/include/unwind-itanium.h
+++ b/sources/cxx-stl/gabi++/include/unwind-itanium.h
@@ -68,9 +68,20 @@
 struct _Unwind_Exception {
   uint64_t exception_class;
   _Unwind_Exception_Cleanup_Fn exception_cleanup;
-  uint64_t private_1;
-  uint64_t private_2;
-} __attribute__((__aligned__)); // must be double-word aligned
+  uint32_t private_1;
+  uint32_t private_2;
+}
+#if defined(__clang__) && defined(__mips__)
+// FIXME: It seems that mipsel-linux-android-gcc will use 24 as the object size
+// with or without the aligned attribute.  However, clang (mipsel) will align
+// the object size to 32 when we specify the aligned attribute, which may
+// result in some sort of incompatibility.  As a workaround, let's remove this
+// attribute when we are compiling this file for MIPS architecture with clang.
+// Add the attribute back when clang can have same behavior as gcc.
+#else
+__attribute__((__aligned__)) // must be double-word aligned
+#endif
+;
 
 _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception*);
 void _Unwind_Resume(struct _Unwind_Exception*);
diff --git a/tests/device/test-unwind-struct/jni/Android.mk b/tests/device/test-unwind-struct/jni/Android.mk
new file mode 100644
index 0000000..ae4d92b
--- /dev/null
+++ b/tests/device/test-unwind-struct/jni/Android.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_unwind_struct
+LOCAL_SRC_FILES := main.c
+LOCAL_STATIC_LIBRARIES := gabi++_static
+include $(BUILD_EXECUTABLE)
+
+$(call import-module,cxx-stl/gabi++)
diff --git a/tests/device/test-unwind-struct/jni/Application.mk b/tests/device/test-unwind-struct/jni/Application.mk
new file mode 100644
index 0000000..a0e3100
--- /dev/null
+++ b/tests/device/test-unwind-struct/jni/Application.mk
@@ -0,0 +1,2 @@
+APP_ABI := all
+APP_STL := none
diff --git a/tests/device/test-unwind-struct/jni/main.c b/tests/device/test-unwind-struct/jni/main.c
new file mode 100644
index 0000000..5acf48e
--- /dev/null
+++ b/tests/device/test-unwind-struct/jni/main.c
@@ -0,0 +1,40 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "unwind.h"
+
+int main() {
+#define CHECK_EQ(EXPECTED_VALUE, ACTUAL_VALUE) \
+  do { \
+    if ((int)(EXPECTED_VALUE) != (int)(ACTUAL_VALUE)) { \
+      fprintf(stderr, "ASSERTION FAILURE: %s %d\n", __FILE__, __LINE__); \
+      fprintf(stderr, "  expected value: %d (%s)\n", \
+              (int)(EXPECTED_VALUE), #EXPECTED_VALUE); \
+      fprintf(stderr, "  actual value: %d (%s)\n", \
+              (int)(ACTUAL_VALUE), #ACTUAL_VALUE); \
+      exit(EXIT_FAILURE); \
+    } \
+  } while (0)
+
+#if defined(__arm__)
+  CHECK_EQ(88, sizeof(struct _Unwind_Control_Block));
+  CHECK_EQ(0, offsetof(struct _Unwind_Control_Block, exception_class));
+  CHECK_EQ(8, offsetof(struct _Unwind_Control_Block, exception_cleanup));
+#elif defined(__mips__)
+  CHECK_EQ(24, sizeof(struct _Unwind_Exception));
+  CHECK_EQ(0, offsetof(struct _Unwind_Exception, exception_class));
+  CHECK_EQ(8, offsetof(struct _Unwind_Exception, exception_cleanup));
+  CHECK_EQ(12, offsetof(struct _Unwind_Exception, private_1));
+  CHECK_EQ(16, offsetof(struct _Unwind_Exception, private_2));
+#elif defined(__i386__)
+  CHECK_EQ(32, sizeof(struct _Unwind_Exception));
+  CHECK_EQ(0, offsetof(struct _Unwind_Exception, exception_class));
+  CHECK_EQ(8, offsetof(struct _Unwind_Exception, exception_cleanup));
+  CHECK_EQ(12, offsetof(struct _Unwind_Exception, private_1));
+  CHECK_EQ(16, offsetof(struct _Unwind_Exception, private_2));
+#else
+#error "unsupported architecture"
+#endif
+
+  return EXIT_SUCCESS;
+}