Merge "Better way to override NDK_TOOLCHAIN_VERSION at command line"
diff --git a/build/tools/build-gabi++.sh b/build/tools/build-gabi++.sh
index 00969c9..983bebf 100755
--- a/build/tools/build-gabi++.sh
+++ b/build/tools/build-gabi++.sh
@@ -98,7 +98,7 @@
 GABIXX_SRCDIR=$ANDROID_NDK_ROOT/$GABIXX_SUBDIR
 
 # Compiler flags we want to use
-GABIXX_CFLAGS="-fPIC -O2 -DANDROID -D__ANDROID__"
+GABIXX_CFLAGS="-fPIC -O2 -DANDROID -D__ANDROID__ -ffunction-sections"
 GABIXX_CFLAGS=$GABIXX_CFLAGS" -I$GABIXX_SRCDIR/include"
 GABIXX_CXXFLAGS="-fuse-cxa-atexit -fexceptions -frtti"
 GABIXX_LDFLAGS="-ldl"
diff --git a/build/tools/build-libportable.sh b/build/tools/build-libportable.sh
index 7ea6dfe..646d814 100755
--- a/build/tools/build-libportable.sh
+++ b/build/tools/build-libportable.sh
@@ -91,7 +91,7 @@
 LIBPORTABLE_SRCDIR_BASE=$ANDROID_NDK_ROOT/../development/ndk/$LIBPORTABLE_SUBDIR
 
 # Compiler flags we want to use
-LIBPORTABLE_CFLAGS="-fPIC -O2 -DANDROID -D__ANDROID__" # ToDo: -ffunction-sections -fdata-sections
+LIBPORTABLE_CFLAGS="-fPIC -O2 -DANDROID -D__ANDROID__ -ffunction-sections"
 LIBPORTABLE_CFLAGS=$LIBPORTABLE_CFLAGS" -I$LIBPORTABLE_SRCDIR_BASE/common/include -D__HOST__"
 LIBPORTABLE_CXXFLAGS="-fno-exceptions -fno-rtti"
 LIBPORTABLE_LDFLAGS=""
@@ -151,7 +151,8 @@
   #    g++ -Wl,@/path/to/libportable.wrap
   #
     nm -a $DSTDIR/libportable.a | grep -r __wrap_ | awk '{print $3}' | sed '/^$/d' | \
-        sed 's/^__wrap_//g' | sort | awk '{printf "--wrap=%s\n",$1}' > "$DSTDIR/libportable.wrap"
+        sed 's/_wrap_/|/' | awk -F'|' '{print $2}' | sort | uniq | \
+        awk '{printf "--wrap=%s\n",$1}' > "$DSTDIR/libportable.wrap"
 }
 
 for ABI in $ABIS; do
diff --git a/build/tools/build-stlport.sh b/build/tools/build-stlport.sh
index f6dce8f..aab5d50 100755
--- a/build/tools/build-stlport.sh
+++ b/build/tools/build-stlport.sh
@@ -95,14 +95,14 @@
 fail_panic "Could not create build directory: $BUILD_DIR"
 
 GABIXX_SRCDIR=$ANDROID_NDK_ROOT/$GABIXX_SUBDIR
-GABIXX_CFLAGS="-fPIC -O2 -DANDROID -D__ANDROID__ -I$GABIXX_SRCDIR/include"
+GABIXX_CFLAGS="-fPIC -O2 -DANDROID -D__ANDROID__ -I$GABIXX_SRCDIR/include -ffunction-sections"
 GABIXX_CXXFLAGS="-fexceptions -frtti"
 GABIXX_SOURCES=$(cd $ANDROID_NDK_ROOT/$GABIXX_SUBDIR && ls src/*.cc)
 GABIXX_LDFLAGS="-ldl"
 
 # Location of the STLPort source tree
 STLPORT_SRCDIR=$ANDROID_NDK_ROOT/$STLPORT_SUBDIR
-STLPORT_CFLAGS="-DGNU_SOURCE -fPIC -O2 -I$STLPORT_SRCDIR/stlport -DANDROID -D__ANDROID__"
+STLPORT_CFLAGS="-DGNU_SOURCE -fPIC -O2 -I$STLPORT_SRCDIR/stlport -DANDROID -D__ANDROID__ -ffunction-sections"
 STLPORT_CFLAGS=$STLPORT_CFLAGS" -I$ANDROID_NDK_ROOT/$GABIXX_SUBDIR/include"
 STLPORT_CXXFLAGS="-fuse-cxa-atexit -fexceptions -frtti"
 STLPORT_SOURCES=\
diff --git a/build/tools/builder-funcs.sh b/build/tools/builder-funcs.sh
index b70868d..5fedd58 100644
--- a/build/tools/builder-funcs.sh
+++ b/build/tools/builder-funcs.sh
@@ -311,6 +311,7 @@
         _BUILD_AR=${AR:-ar}
     fi
     builder_log "${_BUILD_PREFIX}Archive: $libname"
+    rm -f "$lib"
     builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS"
     fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
 }
@@ -332,6 +333,7 @@
         _BUILD_AR=${AR:-ar}
     fi
     builder_log "${_BUILD_PREFIX}Archive: $libname"
+    rm -f "$lib"
     builder_command ${_BUILD_AR} crs "$lib" "$_BUILD_OBJECTS"
     fail_panic "Could not archive ${_BUILD_PREFIX}$libname objects!"
 }
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;
+}