am 30517a93: Merge "DO NOT MERGE: Update netlink-related kernel includes" into honeycomb-LTE

* commit '30517a9344a8ac06b6962bfb24bb33463767307e':
  DO NOT MERGE: Update netlink-related kernel includes
diff --git a/libc/Android.mk b/libc/Android.mk
index 647739e..9877000 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -361,10 +361,10 @@
 	arch-arm/bionic/sigsetjmp.S \
 	arch-arm/bionic/strlen.c.arm \
 	arch-arm/bionic/strcpy.S \
+	arch-arm/bionic/strcmp.S \
 	arch-arm/bionic/syscall.S \
 	string/memmove.c.arm \
 	string/bcopy.c \
-	string/strcmp.c \
 	string/strncmp.c \
 	unistd/socketcalls.c
 
@@ -480,7 +480,8 @@
 		-DINET6 \
 		-I$(LOCAL_PATH)/private \
 		-DUSE_DL_PREFIX \
-		-DPOSIX_MISTAKE
+		-DPOSIX_MISTAKE \
+                -DLOG_ON_HEAP_ERROR \
 
 # these macro definitions are required to implement the
 # 'timezone' and 'daylight' global variables, as well as
@@ -508,7 +509,13 @@
     libc_common_cflags += -DHAVE_ARM_TLS_REGISTER
   endif
 else # !arm
-  libc_crt_target_cflags :=
+  ifeq ($(TARGET_ARCH),x86)
+    libc_crt_target_cflags := -m32
+
+    # Enable recent IA friendly memory routines (such as for Atom)
+    # These will not work on the earlier x86 machines
+    libc_common_cflags += -mtune=i686 -DUSE_SSSE3 -DUSE_SSE2
+  endif # x86
 endif # !arm
 
 # Define ANDROID_SMP appropriately.
@@ -523,6 +530,10 @@
 #
 libc_crt_target_cflags += -I$(LOCAL_PATH)/private
 
+ifeq ($(TARGET_ARCH),arm)
+libc_crt_target_cflags += -DCRT_LEGACY_WORKAROUND
+endif
+
 # Define some common includes
 # ========================================================
 libc_common_c_includes := \
@@ -551,18 +562,24 @@
 # that will call __cxa_finalize(&__dso_handle) in order to ensure that
 # static C++ destructors are properly called on dlclose().
 #
+
+libc_crt_target_so_cflags := $(libc_crt_target_cflags)
+ifeq ($(TARGET_ARCH),x86)
+    # This flag must be added for x86 targets, but not for ARM
+    libc_crt_target_so_cflags += -fPIC
+endif
 GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_so.o
 $(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.S
 	@mkdir -p $(dir $@)
-	$(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
+	$(TARGET_CC) $(libc_crt_target_so_cflags) -o $@ -c $<
 ALL_GENERATED_SOURCES += $(GEN)
 
 GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtend_so.o
 $(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtend_so.S
 	@mkdir -p $(dir $@)
-	$(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
+	$(TARGET_CC) $(libc_crt_target_so_cflags) -o $@ -c $<
 ALL_GENERATED_SOURCES += $(GEN)
-endif # TARGET_ARCH == x86
+endif # TARGET_ARCH == x86 || TARGET_ARCH == arm
 
 
 GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_static.o
@@ -598,6 +615,9 @@
 
 LOCAL_SRC_FILES := $(libc_common_src_files)
 LOCAL_CFLAGS := $(libc_common_cflags)
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_CFLAGS += -DCRT_LEGACY_WORKAROUND
+endif
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
 LOCAL_MODULE := libc_common
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index d698133..46e7b1f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -76,6 +76,8 @@
 pid_t   vfork(void)  190,-1,190
 int     setregid:setregid32(gid_t, gid_t)  204
 int     chroot(const char *)  61
+# IMPORTANT: Even though <sys/prctl.h> declares prctl(int,...), the syscall stub must take 6 arguments
+#            to match the kernel implementation.
 int     prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5)  172
 int     capget(cap_user_header_t header, cap_user_data_t data) 184
 int     capset(cap_user_header_t header, const cap_user_data_t data) 185
diff --git a/libc/arch-arm/bionic/atexit.S b/libc/arch-arm/bionic/atexit.S
new file mode 100644
index 0000000..aa1e18d
--- /dev/null
+++ b/libc/arch-arm/bionic/atexit.S
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CRT_LEGACY_WORKAROUND
+	.arch armv5te
+	.fpu softvfp
+	.eabi_attribute 20, 1
+	.eabi_attribute 21, 1
+	.eabi_attribute 23, 3
+	.eabi_attribute 24, 1
+	.eabi_attribute 25, 1
+	.eabi_attribute 26, 2
+	.eabi_attribute 30, 4
+	.eabi_attribute 18, 4
+	.code	16
+	.section	.text.atexit,"ax",%progbits
+	.align	2
+	.global	atexit
+	.hidden	atexit
+	.code	16
+	.thumb_func
+	.type	atexit, %function
+atexit:
+	.fnstart
+.LFB0:
+	.save	{r4, lr}
+	push	{r4, lr}
+.LCFI0:
+	ldr	r3, .L3
+	mov	r1, #0
+	@ sp needed for prologue
+.LPIC0:
+	add	r3, pc
+	ldr	r2, [r3]
+	bl	__cxa_atexit
+	pop	{r4, pc}
+.L4:
+	.align	2
+.L3:
+	.word	__dso_handle-(.LPIC0+4)
+.LFE0:
+	.fnend
+	.size	atexit, .-atexit
+#endif
diff --git a/libc/arch-arm/bionic/crtbegin_dynamic.S b/libc/arch-arm/bionic/crtbegin_dynamic.S
index d18e715..0999084 100644
--- a/libc/arch-arm/bionic/crtbegin_dynamic.S
+++ b/libc/arch-arm/bionic/crtbegin_dynamic.S
@@ -85,3 +85,4 @@
 	.long -1
 
 #include "__dso_handle.S"
+#include "atexit.S"
diff --git a/libc/arch-arm/bionic/crtbegin_so.S b/libc/arch-arm/bionic/crtbegin_so.S
index bb6b3e2..9275b1e 100644
--- a/libc/arch-arm/bionic/crtbegin_so.S
+++ b/libc/arch-arm/bionic/crtbegin_so.S
@@ -52,4 +52,10 @@
         .long -1
         .long __on_dlclose
 
+#ifdef CRT_LEGACY_WORKAROUND
 #include "__dso_handle.S"
+#else
+#include "__dso_handle_so.S"
+#endif
+
+#include "atexit.S"
diff --git a/libc/arch-arm/bionic/crtbegin_static.S b/libc/arch-arm/bionic/crtbegin_static.S
index 6f9cf25..13b05b2 100644
--- a/libc/arch-arm/bionic/crtbegin_static.S
+++ b/libc/arch-arm/bionic/crtbegin_static.S
@@ -86,3 +86,4 @@
 
 
 #include "__dso_handle.S"
+#include "atexit.S"
diff --git a/libc/arch-arm/bionic/strcmp.S b/libc/arch-arm/bionic/strcmp.S
new file mode 100644
index 0000000..9fdbd56
--- /dev/null
+++ b/libc/arch-arm/bionic/strcmp.S
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2011 The Android Open Source Project
+ * Copyright (c) 2008 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/cpu-features.h>
+
+	.text
+
+	.global strcmp
+	.type strcmp, %function
+	.align 4
+
+#ifdef __ARMEB__
+#define SHFT2LSB lsl
+#define SHFT2LSBEQ lsleq
+#define SHFT2MSB lsr
+#define SHFT2MSBEQ lsreq
+#define MSB 0x000000ff
+#define LSB 0xff000000
+#else
+#define SHFT2LSB lsr
+#define SHFT2LSBEQ lsreq
+#define SHFT2MSB lsl
+#define SHFT2MSBEQ lsleq
+#define MSB 0xff000000
+#define LSB 0x000000ff
+#endif
+
+#define magic1(REG) REG
+#define magic2(REG) REG, lsl #7
+
+strcmp:
+	.fnstart
+	PLD(r0, #0)
+	PLD(r1, #0)
+	eor	r2, r0, r1
+	tst	r2, #3
+
+	/* Strings not at same byte offset from a word boundary.  */
+	bne	.Lstrcmp_unaligned
+	ands	r2, r0, #3
+	bic	r0, r0, #3
+	bic	r1, r1, #3
+	ldr	ip, [r0], #4
+	it	eq
+	ldreq	r3, [r1], #4
+	beq	1f
+
+	/* Although s1 and s2 have identical initial alignment, they are
+	 * not currently word aligned.  Rather than comparing bytes,
+	 * make sure that any bytes fetched from before the addressed
+	 * bytes are forced to 0xff.  Then they will always compare
+	 * equal.
+	 */
+	eor	r2, r2, #3
+	lsl	r2, r2, #3
+	mvn	r3, #MSB
+	SHFT2LSB	r2, r3, r2
+	ldr	r3, [r1], #4
+	orr	ip, ip, r2
+	orr	r3, r3, r2
+1:
+	/* Load the 'magic' constant 0x01010101. */
+	str	r4, [sp, #-4]!
+	mov	r4, #1
+	orr	r4, r4, r4, lsl #8
+	orr	r4, r4, r4, lsl #16
+	.p2align	2
+4:
+	PLD(r0, #8)
+	PLD(r1, #8)
+	sub	r2, ip, magic1(r4)
+	cmp	ip, r3
+	itttt	eq
+
+	/* check for any zero bytes in first word */
+	biceq	r2, r2, ip
+	tsteq	r2, magic2(r4)
+	ldreq	ip, [r0], #4
+	ldreq	r3, [r1], #4
+	beq	4b
+2:
+	/* There's a zero or a different byte in the word */
+	SHFT2MSB	r0, ip, #24
+	SHFT2LSB	ip, ip, #8
+	cmp	r0, #1
+	it	cs
+	cmpcs	r0, r3, SHFT2MSB #24
+	it	eq
+	SHFT2LSBEQ r3, r3, #8
+	beq	2b
+	/* On a big-endian machine, r0 contains the desired byte in bits
+	 * 0-7; on a little-endian machine they are in bits 24-31.  In
+	 * both cases the other bits in r0 are all zero.  For r3 the
+	 * interesting byte is at the other end of the word, but the
+	 * other bits are not necessarily zero.  We need a signed result
+	 * representing the differnece in the unsigned bytes, so for the
+	 * little-endian case we can't just shift the interesting bits up.
+	 */
+#ifdef __ARMEB__
+	sub	r0, r0, r3, lsr #24
+#else
+	and	r3, r3, #255
+	/* No RSB instruction in Thumb2 */
+#ifdef __thumb2__
+	lsr	r0, r0, #24
+	sub	r0, r0, r3
+#else
+	rsb	r0, r3, r0, lsr #24
+#endif
+#endif
+	ldr	r4, [sp], #4
+	bx	lr
+	.fnend
+
+.Lstrcmp_unaligned:
+	wp1 .req r0
+	wp2 .req r1
+	b1  .req r2
+	w1  .req r4
+	w2  .req r5
+	t1  .req ip
+	@ r3 is scratch
+
+	/* First of all, compare bytes until wp1(sp1) is word-aligned. */
+1:
+	tst	wp1, #3
+	beq	2f
+	ldrb	r2, [wp1], #1
+	ldrb	r3, [wp2], #1
+	cmp	r2, #1
+	it	cs
+	cmpcs	r2, r3
+	beq	1b
+	sub	r0, r2, r3
+	bx	lr
+
+2:
+	str	r5, [sp, #-4]!
+	str	r4, [sp, #-4]!
+	mov	b1, #1
+	orr	b1, b1, b1, lsl #8
+	orr	b1, b1, b1, lsl #16
+
+	and	t1, wp2, #3
+	bic	wp2, wp2, #3
+	ldr	w1, [wp1], #4
+	ldr	w2, [wp2], #4
+	cmp	t1, #2
+	beq	2f
+	bhi	3f
+
+	/* Critical inner Loop: Block with 3 bytes initial overlap */
+	.p2align	2
+1:
+	bic	t1, w1, #MSB
+	cmp	t1, w2, SHFT2LSB #8
+	sub	r3, w1, b1
+	bic	r3, r3, w1
+	bne	4f
+	ands	r3, r3, b1, lsl #7
+	it	eq
+	ldreq	w2, [wp2], #4
+	bne	5f
+	eor	t1, t1, w1
+	cmp	t1, w2, SHFT2MSB #24
+	bne	6f
+	ldr	w1, [wp1], #4
+	b	1b
+4:
+	SHFT2LSB	w2, w2, #8
+	b	8f
+
+5:
+#ifdef __ARMEB__
+	/* The syndrome value may contain false ones if the string ends
+	 * with the bytes 0x01 0x00
+	 */
+	tst	w1, #0xff000000
+	itt	ne
+	tstne	w1, #0x00ff0000
+	tstne	w1, #0x0000ff00
+	beq	7f
+#else
+	bics	r3, r3, #0xff000000
+	bne	7f
+#endif
+	ldrb	w2, [wp2]
+	SHFT2LSB	t1, w1, #24
+#ifdef __ARMEB__
+	lsl	w2, w2, #24
+#endif
+	b	8f
+
+6:
+	SHFT2LSB	t1, w1, #24
+	and	w2, w2, #LSB
+	b	8f
+
+	/* Critical inner Loop: Block with 2 bytes initial overlap */
+	.p2align	2
+2:
+	SHFT2MSB	t1, w1, #16
+	sub	r3, w1, b1
+	SHFT2LSB	t1, t1, #16
+	bic	r3, r3, w1
+	cmp	t1, w2, SHFT2LSB #16
+	bne	4f
+	ands	r3, r3, b1, lsl #7
+	it	eq
+	ldreq	w2, [wp2], #4
+	bne	5f
+	eor	t1, t1, w1
+	cmp	t1, w2, SHFT2MSB #16
+	bne	6f
+	ldr	w1, [wp1], #4
+	b	2b
+
+5:
+#ifdef __ARMEB__
+	/* The syndrome value may contain false ones if the string ends
+	 * with the bytes 0x01 0x00
+	 */
+	tst	w1, #0xff000000
+	it	ne
+	tstne	w1, #0x00ff0000
+	beq	7f
+#else
+	lsls	r3, r3, #16
+	bne	7f
+#endif
+	ldrh	w2, [wp2]
+	SHFT2LSB	t1, w1, #16
+#ifdef __ARMEB__
+	lsl	w2, w2, #16
+#endif
+	b	8f
+
+6:
+	SHFT2MSB	w2, w2, #16
+	SHFT2LSB	t1, w1, #16
+4:
+	SHFT2LSB	w2, w2, #16
+	b	8f
+
+	/* Critical inner Loop: Block with 1 byte initial overlap */
+	.p2align	2
+3:
+	and	t1, w1, #LSB
+	cmp	t1, w2, SHFT2LSB #24
+	sub	r3, w1, b1
+	bic	r3, r3, w1
+	bne	4f
+	ands	r3, r3, b1, lsl #7
+	it	eq
+	ldreq	w2, [wp2], #4
+	bne	5f
+	eor	t1, t1, w1
+	cmp	t1, w2, SHFT2MSB #8
+	bne	6f
+	ldr	w1, [wp1], #4
+	b	3b
+4:
+	SHFT2LSB	w2, w2, #24
+	b	8f
+5:
+	/* The syndrome value may contain false ones if the string ends
+	 * with the bytes 0x01 0x00
+	 */
+	tst	w1, #LSB
+	beq	7f
+	ldr	w2, [wp2], #4
+6:
+	SHFT2LSB	t1, w1, #8
+	bic	w2, w2, #MSB
+	b	8f
+7:
+	mov	r0, #0
+	ldr	r4, [sp], #4
+	ldr	r5, [sp], #4
+	bx	lr
+
+8:
+	and	r2, t1, #LSB
+	and	r0, w2, #LSB
+	cmp	r0, #1
+	it	cs
+	cmpcs	r0, r2
+	itt	eq
+	SHFT2LSBEQ	t1, t1, #8
+	SHFT2LSBEQ	w2, w2, #8
+	beq	8b
+	sub	r0, r2, r0
+	ldr	r4, [sp], #4
+	ldr	r5, [sp], #4
+	bx	lr
diff --git a/libc/arch-x86/bionic/__stack_chk_fail_local.S b/libc/arch-x86/bionic/__stack_chk_fail_local.S
new file mode 100644
index 0000000..59fe86e
--- /dev/null
+++ b/libc/arch-x86/bionic/__stack_chk_fail_local.S
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+	.text
+	.p2align 4,,15
+	.globl	__stack_chk_fail_local
+	.hidden	__stack_chk_fail_local
+	.type	__stack_chk_fail_local, @function
+
+__stack_chk_fail_local:
+#ifdef __PIC__
+	pushl	%ebx
+	call	__x86.get_pc_thunk.bx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	call	__stack_chk_fail@PLT
+#else /* PIC */
+	jmp   __stack_chk_fail
+#endif /* not PIC */
+
+	.size	__stack_chk_fail_local, .-__stack_chk_fail_local
diff --git a/libc/arch-x86/bionic/atexit.S b/libc/arch-x86/bionic/atexit.S
new file mode 100644
index 0000000..b28f40b
--- /dev/null
+++ b/libc/arch-x86/bionic/atexit.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+	.text
+	.p2align 4,,15
+	.globl	atexit
+	.hidden	atexit
+	.type	atexit, @function
+atexit:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	call	__x86.get_pc_thunk.bx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	subl	$20, %esp
+	movl	$0, 4(%esp)
+	movl	__dso_handle@GOTOFF(%ebx), %eax
+	movl	%eax, 8(%esp)
+	movl	8(%ebp), %eax
+	movl	%eax, (%esp)
+	call	__cxa_atexit@PLT
+	addl	$20, %esp
+	popl	%ebx
+	popl	%ebp
+	ret
+	.size	atexit, .-atexit
+
+	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+	.globl	__x86.get_pc_thunk.bx
+	.hidden	__x86.get_pc_thunk.bx
+	.type	__x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	movl	(%esp), %ebx
+	ret
diff --git a/libc/arch-x86/bionic/crtbegin_dynamic.S b/libc/arch-x86/bionic/crtbegin_dynamic.S
index 0a7bc62..9ba0d2f 100644
--- a/libc/arch-x86/bionic/crtbegin_dynamic.S
+++ b/libc/arch-x86/bionic/crtbegin_dynamic.S
@@ -76,10 +76,62 @@
 	.globl __INIT_ARRAY__
 __INIT_ARRAY__:
 	.long -1
+	.long	frame_dummy
 
 	.section .fini_array, "aw"
 	.globl __FINI_ARRAY__
 __FINI_ARRAY__:
 	.long -1
+	.long	__do_global_dtors_aux
+
+	.section	.eh_frame,"a",@progbits
+	.align 4
+	.type	__EH_FRAME_BEGIN__, @object
+__EH_FRAME_BEGIN__:
+	.text
+	.p2align 4,,15
+	.type	__do_global_dtors_aux, @function
+__do_global_dtors_aux:
+	pushl	%ebp
+	movl	%esp, %ebp
+	subl	$24, %esp
+	cmpb	$0, completed.4454
+	jne	.L4
+	movl	$__deregister_frame_info_bases, %eax
+	testl	%eax, %eax
+	je	.L3
+	movl	$__EH_FRAME_BEGIN__, (%esp)
+	call	__deregister_frame_info_bases
+.L3:
+	movb	$1, completed.4454
+.L4:
+	leave
+	ret
+	.text
+	.p2align 4,,15
+	.type	frame_dummy, @function
+frame_dummy:
+	pushl	%ebp
+	movl	$__register_frame_info_bases, %eax
+	movl	%esp, %ebp
+	subl	$24, %esp
+	testl	%eax, %eax
+	je	.L7
+	movl	%ebx, 12(%esp)
+	movl	$0, 8(%esp)
+	movl	$object.4466, 4(%esp)
+	movl	$__EH_FRAME_BEGIN__, (%esp)
+	call	__register_frame_info_bases
+.L7:
+	leave
+	ret
+	.local	completed.4454
+	.comm	completed.4454,1,1
+	.local	object.4466
+	.comm	object.4466,24,4
+	.weak	__register_frame_info_bases
+	.weak	__deregister_frame_info_bases
 
 #include "__dso_handle.S"
+#include "atexit.S"
+#include "__stack_chk_fail_local.S"
diff --git a/libc/arch-x86/bionic/crtbegin_so.S b/libc/arch-x86/bionic/crtbegin_so.S
index b3a01b5..99662fe 100644
--- a/libc/arch-x86/bionic/crtbegin_so.S
+++ b/libc/arch-x86/bionic/crtbegin_so.S
@@ -1,9 +1,30 @@
-# This function is to be called when the shared library
-# is unloaded through dlclose()
-_on_dlclose:
-    lea __dso_handle, %eax
-    call __cxa_finalize
-    ret
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 .section .init_array, "aw"
 .align 4
@@ -11,6 +32,7 @@
 .globl __INIT_ARRAY__
 __INIT_ARRAY__:
     .long -1
+    .long frame_dummy
 
 .section .fini_array, "aw"
 .align 4
@@ -18,6 +40,72 @@
 .globl __FINI_ARRAY__
 __FINI_ARRAY__:
     .long -1
-    .long _on_dlclose
+    .long __do_global_dtors_aux
 
-#include "__dso_handle.S"
+	.section	.eh_frame,"a",@progbits
+	.align 4
+	.type	__EH_FRAME_BEGIN__, @object
+__EH_FRAME_BEGIN__:
+	.text
+	.p2align 4,,15
+	.type	__do_global_dtors_aux, @function
+__do_global_dtors_aux:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	call	__x86.get_pc_thunk.bx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	subl	$20, %esp
+	cmpb	$0, completed.4454@GOTOFF(%ebx)
+	jne	.L5
+	movl	__dso_handle@GOTOFF(%ebx), %eax
+	movl	%eax, (%esp)
+	call	__cxa_finalize@PLT
+	movl	__deregister_frame_info_bases@GOT(%ebx), %eax
+	testl	%eax, %eax
+	je	.L4
+	leal	__EH_FRAME_BEGIN__@GOTOFF(%ebx), %eax
+	movl	%eax, (%esp)
+	call	__deregister_frame_info_bases@PLT
+.L4:
+	movb	$1, completed.4454@GOTOFF(%ebx)
+.L5:
+	addl	$20, %esp
+	popl	%ebx
+	popl	%ebp
+	ret
+	.text
+	.p2align 4,,15
+	.type	frame_dummy, @function
+frame_dummy:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	call	__x86.get_pc_thunk.bx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	subl	$20, %esp
+	movl	__register_frame_info_bases@GOT(%ebx), %eax
+	testl	%eax, %eax
+	je	.L8
+	leal	object.4469@GOTOFF(%ebx), %eax
+	movl	%eax, 4(%esp)
+	leal	__EH_FRAME_BEGIN__@GOTOFF(%ebx), %eax
+	movl	%ebx, 12(%esp)
+	movl	$0, 8(%esp)
+	movl	%eax, (%esp)
+	call	__register_frame_info_bases@PLT
+.L8:
+	addl	$20, %esp
+	popl	%ebx
+	popl	%ebp
+	ret
+	.local	completed.4454
+	.comm	completed.4454,1,1
+	.local	object.4469
+	.comm	object.4469,24,4
+	.weak	__register_frame_info_bases
+	.weak	__deregister_frame_info_bases
+
+#include "__dso_handle_so.S"
+#include "atexit.S"
+#include "__stack_chk_fail_local.S"
diff --git a/libc/arch-x86/bionic/crtbegin_static.S b/libc/arch-x86/bionic/crtbegin_static.S
index d5c2430..8e70330 100644
--- a/libc/arch-x86/bionic/crtbegin_static.S
+++ b/libc/arch-x86/bionic/crtbegin_static.S
@@ -75,10 +75,62 @@
 	.globl __INIT_ARRAY__
 __INIT_ARRAY__:
 	.long -1
+	.long	frame_dummy
 
 	.section .fini_array, "aw"
 	.globl __FINI_ARRAY__
 __FINI_ARRAY__:
 	.long -1
+	.long	__do_global_dtors_aux
+
+	.section	.eh_frame,"a",@progbits
+	.align 4
+	.type	__EH_FRAME_BEGIN__, @object
+__EH_FRAME_BEGIN__:
+	.text
+	.p2align 4,,15
+	.type	__do_global_dtors_aux, @function
+__do_global_dtors_aux:
+	pushl	%ebp
+	movl	%esp, %ebp
+	subl	$24, %esp
+	cmpb	$0, completed.4454
+	jne	.L4
+	movl	$__deregister_frame_info_bases, %eax
+	testl	%eax, %eax
+	je	.L3
+	movl	$__EH_FRAME_BEGIN__, (%esp)
+	call	__deregister_frame_info_bases
+.L3:
+	movb	$1, completed.4454
+.L4:
+	leave
+	ret
+	.text
+	.p2align 4,,15
+	.type	frame_dummy, @function
+frame_dummy:
+	pushl	%ebp
+	movl	$__register_frame_info_bases, %eax
+	movl	%esp, %ebp
+	subl	$24, %esp
+	testl	%eax, %eax
+	je	.L7
+	movl	%ebx, 12(%esp)
+	movl	$0, 8(%esp)
+	movl	$object.4466, 4(%esp)
+	movl	$__EH_FRAME_BEGIN__, (%esp)
+	call	__register_frame_info_bases
+.L7:
+	leave
+	ret
+	.local	completed.4454
+	.comm	completed.4454,1,1
+	.local	object.4466
+	.comm	object.4466,24,4
+	.weak	__register_frame_info_bases
+	.weak	__deregister_frame_info_bases
 
 #include "__dso_handle.S"
+#include "atexit.S"
+#include "__stack_chk_fail_local.S"
diff --git a/libc/arch-x86/bionic/crtend.S b/libc/arch-x86/bionic/crtend.S
index 884ba8b..68447e7 100644
--- a/libc/arch-x86/bionic/crtend.S
+++ b/libc/arch-x86/bionic/crtend.S
@@ -6,3 +6,10 @@
 
 	.section .fini_array, "aw"
 	.long 0
+
+	.section	.eh_frame,"a",@progbits
+	.align 4
+	.type	__FRAME_END__, @object
+	.size	__FRAME_END__, 4
+__FRAME_END__:
+	.zero	4
diff --git a/libc/arch-x86/bionic/crtend_so.S b/libc/arch-x86/bionic/crtend_so.S
index 8c9d419..63e58b9 100644
--- a/libc/arch-x86/bionic/crtend_so.S
+++ b/libc/arch-x86/bionic/crtend_so.S
@@ -1,6 +1,12 @@
-
 .section .init_array, "aw"
     .long 0
 
 .section .fini_array, "aw"
     .long 0
+
+	.section	.eh_frame,"a",@progbits
+	.align 4
+	.type	__FRAME_END__, @object
+	.size	__FRAME_END__, 4
+__FRAME_END__:
+	.zero	4
diff --git a/libc/arch-x86/bionic/syscall.S b/libc/arch-x86/bionic/syscall.S
index 71abe6b..3cca85c 100644
--- a/libc/arch-x86/bionic/syscall.S
+++ b/libc/arch-x86/bionic/syscall.S
@@ -20,18 +20,15 @@
     .align 4
 
 syscall:
-    push    %eax
     push    %ebx
-    push    %ecx
-    push    %edx
     push    %esi
     push    %edi
-    mov     28(%esp),%eax
-    mov     32(%esp),%ebx
-    mov     36(%esp),%ecx
-    mov     40(%esp),%edx
-    mov     44(%esp),%esi
-    mov     48(%esp),%edi
+    mov     16(%esp),%eax
+    mov     20(%esp),%ebx
+    mov     24(%esp),%ecx
+    mov     28(%esp),%edx
+    mov     32(%esp),%esi
+    mov     36(%esp),%edi
 
     int     $0x80
 
@@ -45,8 +42,5 @@
 1:
     pop    %edi
     pop    %esi
-    pop    %edx
-    pop    %ecx
     pop    %ebx
-    pop    %eax
     ret
diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c
index 19fbb75..8c75e9c 100644
--- a/libc/bionic/dlmalloc.c
+++ b/libc/bionic/dlmalloc.c
@@ -2265,13 +2265,53 @@
 
 #else /* PROCEED_ON_ERROR */
 
-#ifndef CORRUPTION_ERROR_ACTION
-#define CORRUPTION_ERROR_ACTION(m) ABORT
-#endif /* CORRUPTION_ERROR_ACTION */
+/* The following Android-specific code is used to print an informative
+ * fatal error message to the log when we detect that a heap corruption
+ * was detected. We need to be careful about not using a log function
+ * that may require an allocation here!
+ */
+#ifdef LOG_ON_HEAP_ERROR
 
-#ifndef USAGE_ERROR_ACTION
-#define USAGE_ERROR_ACTION(m,p) ABORT
-#endif /* USAGE_ERROR_ACTION */
+#  include <private/logd.h>
+
+static void __bionic_heap_error(const char* msg, const char* function)
+{
+    /* We format the buffer explicitely, i.e. without using snprintf()
+     * which may use malloc() internally. Not something we can trust
+     * if we just detected a corrupted heap.
+     */
+    char buffer[256];
+    strlcpy(buffer, "@@@ ABORTING: ", sizeof(buffer));
+    strlcat(buffer, msg, sizeof(buffer));
+    if (function != NULL) {
+        strlcat(buffer, " IN ", sizeof(buffer));
+        strlcat(buffer, function, sizeof(buffer));
+    }
+    __libc_android_log_write(ANDROID_LOG_FATAL,"libc",buffer);
+    abort();
+}
+
+#  ifndef CORRUPTION_ERROR_ACTION
+#    define CORRUPTION_ERROR_ACTION(m)  \
+    __bionic_heap_error("HEAP MEMORY CORRUPTION", __FUNCTION__)
+#  endif
+#  ifndef USAGE_ERROR_ACTION
+#    define USAGE_ERROR_ACTION(m,p)   \
+    __bionic_heap_error("INVALID HEAP ADDRESS", __FUNCTION__)
+#  endif
+
+#else /* !LOG_ON_HEAP_ERROR */
+
+#  ifndef CORRUPTION_ERROR_ACTION
+#    define CORRUPTION_ERROR_ACTION(m) ABORT
+#  endif /* CORRUPTION_ERROR_ACTION */
+
+#  ifndef USAGE_ERROR_ACTION
+#    define USAGE_ERROR_ACTION(m,p) ABORT
+#  endif /* USAGE_ERROR_ACTION */
+
+#endif /* !LOG_ON_HEAP_ERROR */
+
 
 #endif /* PROCEED_ON_ERROR */
 
diff --git a/libc/bionic/logd_write.c b/libc/bionic/logd_write.c
index 63dfd59..2bc39fa 100644
--- a/libc/bionic/logd_write.c
+++ b/libc/bionic/logd_write.c
@@ -48,6 +48,16 @@
 
 #include <pthread.h>
 
+/* IMPORTANT IMPORTANT IMPORTANT: TECHNICAL NOTE
+ *
+ * Some of the functions below can be called when our malloc() implementation
+ * has detected that the heap is corrupted, or even from a signal handler.
+ *
+ * These functions should *not* use a function that allocates heap memory
+ * or is not signal-safe. Using direct system calls is acceptable, and we
+ * also assume that pthread_mutex_lock/unlock can be used too.
+ */
+
 #define LOG_BUF_SIZE    1024
 
 typedef enum {
@@ -77,9 +87,10 @@
     { __write_to_log_init, -1, "/dev/"LOGGER_LOG_RADIO }
 };
 
+/* Important: see technical note at start of source file */
 static int __write_to_log_null(log_id_t log_id, struct iovec *vec)
 {
-    /* 
+    /*
      * ALTERED behaviour from previous version
      * always returns successful result
      */
@@ -97,23 +108,21 @@
  *  it's supposed, that log_id contains valid id always.
  *  this check must be performed in higher level functions
  */
+/* Important: see technical note at start of source file */
 static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec)
 {
-    ssize_t ret;
-
-    do {
-        ret = writev(log_channels[log_id].fd, vec, 3);
-    } while ((ret < 0) && (errno == EINTR));
-
-    return ret;
+    return TEMP_FAILURE_RETRY( writev(log_channels[log_id].fd, vec, 3) );
 }
 
+/* Important: see technical note at start of source file */
 static int __write_to_log_init(log_id_t log_id, struct iovec *vec)
 {
     if ((LOG_ID_NONE < log_id) && (log_id < LOG_ID_MAX)) {
+        int fd;
+
         pthread_mutex_lock(&log_init_lock);
 
-        int fd = open(log_channels[log_id].path, O_WRONLY);
+        fd = TEMP_FAILURE_RETRY(open(log_channels[log_id].path, O_WRONLY));
 
         log_channels[log_id].logger =
             (fd < 0) ? __write_to_log_null : __write_to_log_kernel;
@@ -130,7 +139,9 @@
     return -1;
 }
 
-static int __android_log_write(int prio, const char *tag, const char *msg)
+/* Important: see technical note at start of source file */
+__LIBC_HIDDEN__
+int __libc_android_log_write(int prio, const char *tag, const char *msg)
 {
     struct iovec vec[3];
     log_id_t log_id = LOG_ID_MAIN;
@@ -151,7 +162,11 @@
     return log_channels[log_id].logger(log_id, vec);
 }
 
-
+/* The functions below are not designed to be called from a heap panic
+ * function or from a signal handler. As such, they are free to use complex
+ * C library functions like vsnprintf()
+ */
+__LIBC_HIDDEN__
 int __libc_android_log_vprint(int prio, const char *tag, const char *fmt,
                               va_list ap)
 {
@@ -159,9 +174,10 @@
 
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
 
-    return __android_log_write(prio, tag, buf);
+    return __libc_android_log_write(prio, tag, buf);
 }
 
+__LIBC_HIDDEN__
 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...)
 {
     va_list ap;
@@ -171,20 +187,21 @@
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
     va_end(ap);
 
-    return __android_log_write(prio, tag, buf);
+    return __libc_android_log_write(prio, tag, buf);
 }
 
+__LIBC_HIDDEN__
 int __libc_android_log_assert(const char *cond, const char *tag,
 			      const char *fmt, ...)
 {
     va_list ap;
-    char buf[LOG_BUF_SIZE];    
+    char buf[LOG_BUF_SIZE];
 
     va_start(ap, fmt);
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
     va_end(ap);
 
-    __android_log_write(ANDROID_LOG_FATAL, tag, buf);
+    __libc_android_log_write(ANDROID_LOG_FATAL, tag, buf);
 
     exit(1);
 
diff --git a/libc/bionic/malloc_debug_common.c b/libc/bionic/malloc_debug_common.c
index ebf0006..b9fcbc4 100644
--- a/libc/bionic/malloc_debug_common.c
+++ b/libc/bionic/malloc_debug_common.c
@@ -84,7 +84,6 @@
         //
         // This is used for sorting, not determination of equality, so we don't
         // need to compare the bit flags.
-        int result;
         if (alloc1 > alloc2) {
             result = -1;
         } else if (alloc1 < alloc2) {
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 34909fb..0a0854d 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -68,7 +68,13 @@
 #define  __likely(cond)    __builtin_expect(!!(cond), 1)
 #define  __unlikely(cond)  __builtin_expect(!!(cond), 0)
 
-void _thread_created_hook(pid_t thread_id) __attribute__((noinline));
+#ifdef __i386__
+#define ATTRIBUTES __attribute__((noinline)) __attribute__((fastcall))
+#else
+#define ATTRIBUTES __attribute__((noinline))
+#endif
+
+void ATTRIBUTES _thread_created_hook(pid_t thread_id);
 
 #define PTHREAD_ATTR_FLAG_DETACHED      0x00000001
 #define PTHREAD_ATTR_FLAG_USER_STACK    0x00000002
diff --git a/libc/bionic/ptrace.c b/libc/bionic/ptrace.c
index b1ca00c..0bb1acd 100644
--- a/libc/bionic/ptrace.c
+++ b/libc/bionic/ptrace.c
@@ -1,63 +1,68 @@
-/*

- * Copyright (C) 2008 The Android Open Source Project

- * All rights reserved.

- *

- * Redistribution and use in source and binary forms, with or without

- * modification, are permitted provided that the following conditions

- * are met:

- *  * Redistributions of source code must retain the above copyright

- *    notice, this list of conditions and the following disclaimer.

- *  * Redistributions in binary form must reproduce the above copyright

- *    notice, this list of conditions and the following disclaimer in

- *    the documentation and/or other materials provided with the

- *    distribution.

- *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS

- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE

- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,

- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,

- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS

- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED

- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,

- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT

- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

- * SUCH DAMAGE.

- */

-#include <sys/types.h>

-#include <sys/ptrace.h>

-

-extern long __ptrace(int request, pid_t pid, void *addr, void *data);

-

-long ptrace(int request, pid_t pid, void * addr, void * data)

-{

-    switch (request) {

-        case PTRACE_PEEKUSR:

-        case PTRACE_PEEKTEXT:

-        case PTRACE_PEEKDATA:

-        {

-            long word;

-            long ret;

-            

-            ret = __ptrace(request, pid, addr, &word);

-            if (ret == 0) {

-                return word;

-            } else {

-                // __ptrace will set errno for us

-                return -1;

-            }

-        }

-

-        default:

-             return __ptrace(request, pid, addr, data);

-    }

-}

-

-/*

- * Hook for gdb to get notified when a thread is created

- */

-void _thread_created_hook(pid_t thread_id) __attribute__((noinline));

-void _thread_created_hook(pid_t thread_id)

-{

-}

+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
+extern long __ptrace(int request, pid_t pid, void *addr, void *data);
+
+long ptrace(int request, pid_t pid, void * addr, void * data)
+{
+    switch (request) {
+        case PTRACE_PEEKUSR:
+        case PTRACE_PEEKTEXT:
+        case PTRACE_PEEKDATA:
+        {
+            long word;
+            long ret;
+
+            ret = __ptrace(request, pid, addr, &word);
+            if (ret == 0) {
+                return word;
+            } else {
+                // __ptrace will set errno for us
+                return -1;
+            }
+        }
+
+        default:
+             return __ptrace(request, pid, addr, data);
+    }
+}
+
+/*
+ * Hook for gdb to get notified when a thread is created
+ */
+#ifdef __i386__
+#define ATTRIBUTES __attribute__((noinline)) __attribute__((fastcall))
+#else
+#define ATTRIBUTES __attribute__((noinline))
+#endif
+
+void ATTRIBUTES _thread_created_hook(pid_t thread_id)
+{
+}
diff --git a/libc/include/netdb.h b/libc/include/netdb.h
index c2e08ea..9491364 100644
--- a/libc/include/netdb.h
+++ b/libc/include/netdb.h
@@ -209,8 +209,8 @@
 void endprotoent(void);
 void endservent(void);
 void freehostent(struct hostent *);
-struct hostent	*gethostbyaddr(const char *, int, int);
-int gethostbyaddr_r(const char *, int, int, struct hostent *, char *, size_t, struct hostent **, int *);
+struct hostent	*gethostbyaddr(const void *, int, int);
+int gethostbyaddr_r(const void *, int, int, struct hostent *, char *, size_t, struct hostent **, int *);
 struct hostent	*gethostbyname(const char *);
 int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *);
 struct hostent	*gethostbyname2(const char *, int);
diff --git a/libc/include/netinet/ip.h b/libc/include/netinet/ip.h
index 541905c..629ed77 100644
--- a/libc/include/netinet/ip.h
+++ b/libc/include/netinet/ip.h
@@ -83,7 +83,7 @@
 #define	IPTOS_LOWDELAY		0x10
 #define	IPTOS_THROUGHPUT	0x08
 #define	IPTOS_RELIABILITY	0x04
-/*	IPTOS_LOWCOST		0x02 XXX */
+#define	IPTOS_MINCOST		0x02
 #if 1
 /* ECN RFC3168 obsoletes RFC2481, and these will be deprecated soon. */
 #define IPTOS_CE		0x01	/* congestion experienced */
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 9b6da31..92035d4 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -79,7 +79,7 @@
 #define	___STRING(x)	__STRING(x)
 #define	___CONCAT(x,y)	__CONCAT(x,y)
 
-#if __STDC__ || defined(__cplusplus)
+#if defined(__STDC__) || defined(__cplusplus)
 #define	__P(protos)	protos		/* full-blown ANSI C */
 #define	__CONCAT(x,y)	x ## y
 #define	__STRING(x)	#x
@@ -213,7 +213,7 @@
  * C99 defines the restrict type qualifier keyword, which was made available
  * in GCC 2.92.
  */
-#if __STDC_VERSION__ >= 199901L
+#if defined(__STDC__VERSION__) && __STDC_VERSION__ >= 199901L
 #define	__restrict	restrict
 #else
 #if !__GNUC_PREREQ__(2, 92)
@@ -225,7 +225,7 @@
  * C99 defines __func__ predefined identifier, which was made available
  * in GCC 2.95.
  */
-#if !(__STDC_VERSION__ >= 199901L)
+#if !defined(__STDC_VERSION__) || !(__STDC_VERSION__ >= 199901L)
 #if __GNUC_PREREQ__(2, 6)
 #define	__func__	__PRETTY_FUNCTION__
 #elif __GNUC_PREREQ__(2, 4)
diff --git a/libc/include/sys/prctl.h b/libc/include/sys/prctl.h
index ce85bf7..359d684 100644
--- a/libc/include/sys/prctl.h
+++ b/libc/include/sys/prctl.h
@@ -32,8 +32,13 @@
 
 __BEGIN_DECLS
 
-extern int prctl(int option, unsigned long arg2, unsigned long arg3 , unsigned
-               long arg4, unsigned long arg5);
+/* IMPORTANT NOTE: This function is declared as taking a variable number
+ *                 of arguments to match the GLibc definition. However
+ *                 its declaration inside SYSCALLS.TXT *must* make it
+ *                 take 6 arguments to ensure consistency with the kernel
+ *                 implementation.
+ */
+extern int prctl(int option, ...);
 
 __END_DECLS
 
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 4534fb9..d92549f 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -70,8 +70,9 @@
 extern int execle(const char *, const char *, ...);
 extern int capget(cap_user_header_t hdrp, cap_user_data_t datap);
 extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-extern int prctl(int  option,  unsigned long arg2, unsigned long arg3,
-                 unsigned long arg4, unsigned long arg5);
+
+/* IMPORTANT: See comment under <sys/prctl.h> about this declaration */
+extern int prctl(int  option, ...);
 
 extern int nice(int);
 
diff --git a/libc/netbsd/gethnamaddr.c b/libc/netbsd/gethnamaddr.c
index 3ebe53e..fb18869 100644
--- a/libc/netbsd/gethnamaddr.c
+++ b/libc/netbsd/gethnamaddr.c
@@ -637,7 +637,7 @@
 }
 
 struct hostent *
-gethostbyaddr(const char *addr,	/* XXX should have been def'd as u_char! */
+gethostbyaddr(const void *addr,
     socklen_t len, int af)
 {
 	const u_char *uaddr = (const u_char *)addr;
diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c
index a9a67f2..e3ceb5a 100644
--- a/libc/netbsd/resolv/res_cache.c
+++ b/libc/netbsd/resolv/res_cache.c
@@ -35,6 +35,7 @@
 
 #include <errno.h>
 #include "arpa_nameser.h"
+#include <sys/system_properties.h>
 #include <net/if.h>
 #include <netdb.h>
 #include <linux/if.h>
@@ -113,7 +114,7 @@
  */
 #define  CONFIG_SECONDS    (60*10)    /* 10 minutes */
 
-/* maximum number of entries kept in the cache. This value has been
+/* default number of entries kept in the cache. This value has been
  * determined by browsing through various sites and counting the number
  * of corresponding requests. Keep in mind that our framework is currently
  * performing two requests per name lookup (one for IPv4, the other for IPv6)
@@ -132,10 +133,16 @@
  * most high-level websites use lots of media/ad servers with different names
  * but these are generally reused when browsing through the site.
  *
- * As such, a valud of 64 should be relatively conformtable at the moment.
+ * As such, a value of 64 should be relatively comfortable at the moment.
+ *
+ * The system property ro.net.dns_cache_size can be used to override the default
+ * value with a custom value
  */
 #define  CONFIG_MAX_ENTRIES    64
 
+/* name of the system property that can be used to set the cache size */
+#define  DNS_CACHE_SIZE_PROP_NAME   "ro.net.dns_cache_size"
+
 /****************************************************************************/
 /****************************************************************************/
 /*****                                                                  *****/
@@ -1151,15 +1158,15 @@
  * for simplicity, the hash-table fields 'hash' and 'hlink' are
  * inlined in the Entry structure.
  */
-#define  MAX_HASH_ENTRIES   (2*CONFIG_MAX_ENTRIES)
 
 typedef struct resolv_cache {
+    int              max_entries;
     int              num_entries;
     Entry            mru_list;
     pthread_mutex_t  lock;
     unsigned         generation;
     int              last_id;
-    Entry*           entries[ MAX_HASH_ENTRIES ];
+    Entry*           entries;
 } Cache;
 
 typedef struct resolv_cache_info {
@@ -1179,9 +1186,9 @@
     int     nn;
     time_t  now = _time_now();
 
-    for (nn = 0; nn < MAX_HASH_ENTRIES; nn++) 
+    for (nn = 0; nn < cache->max_entries; nn++)
     {
-        Entry**  pnode = &cache->entries[nn];
+        Entry**  pnode = (Entry**) &cache->entries[nn];
 
         while (*pnode != NULL) {
             Entry*  node = *pnode;
@@ -1199,6 +1206,30 @@
          "*************************");
 }
 
+/* Return max number of entries allowed in the cache,
+ * i.e. cache size. The cache size is either defined
+ * by system property ro.net.dns_cache_size or by
+ * CONFIG_MAX_ENTRIES if system property not set
+ * or set to invalid value. */
+static int
+_res_cache_get_max_entries( void )
+{
+    int result = -1;
+    char cache_size[PROP_VALUE_MAX];
+
+    if (__system_property_get(DNS_CACHE_SIZE_PROP_NAME, cache_size) > 0) {
+        result = atoi(cache_size);
+    }
+
+    // ro.net.dns_cache_size not set or set to negative value
+    if (result <= 0) {
+        result = CONFIG_MAX_ENTRIES;
+    }
+
+    XLOG("cache size: %d", result);
+    return result;
+}
+
 static struct resolv_cache*
 _resolv_cache_create( void )
 {
@@ -1206,10 +1237,17 @@
 
     cache = calloc(sizeof(*cache), 1);
     if (cache) {
-        cache->generation = ~0U;
-        pthread_mutex_init( &cache->lock, NULL );
-        cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list;
-        XLOG("%s: cache created\n", __FUNCTION__);
+        cache->max_entries = _res_cache_get_max_entries();
+        cache->entries = calloc(sizeof(*cache->entries), cache->max_entries);
+        if (cache->entries) {
+            cache->generation = ~0U;
+            pthread_mutex_init( &cache->lock, NULL );
+            cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list;
+            XLOG("%s: cache created\n", __FUNCTION__);
+        } else {
+            free(cache);
+            cache = NULL;
+        }
     }
     return cache;
 }
@@ -1300,8 +1338,8 @@
 _cache_lookup_p( Cache*   cache,
                  Entry*   key )
 {
-    int      index = key->hash % MAX_HASH_ENTRIES;
-    Entry**  pnode = &cache->entries[ key->hash % MAX_HASH_ENTRIES ];
+    int      index = key->hash % cache->max_entries;
+    Entry**  pnode = (Entry**) &cache->entries[ index ];
 
     while (*pnode != NULL) {
         Entry*  node = *pnode;
@@ -1482,7 +1520,7 @@
         goto Exit;
     }
 
-    if (cache->num_entries >= CONFIG_MAX_ENTRIES) {
+    if (cache->num_entries >= cache->max_entries) {
         _cache_remove_oldest(cache);
         /* need to lookup again */
         lookup = _cache_lookup_p(cache, key);
diff --git a/libc/private/__dso_handle.S b/libc/private/__dso_handle.S
index fcebab6..3e80128 100644
--- a/libc/private/__dso_handle.S
+++ b/libc/private/__dso_handle.S
@@ -32,6 +32,11 @@
 #
         .section .bss
         .align 4
+
+#ifndef CRT_LEGACY_WORKAROUND
+	.hidden __dso_handle
+#endif
+
         .globl __dso_handle
 __dso_handle:
         .long 0
diff --git a/libc/private/__dso_handle_so.S b/libc/private/__dso_handle_so.S
new file mode 100644
index 0000000..77a5d7f
--- /dev/null
+++ b/libc/private/__dso_handle_so.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+# The __dso_handle global variable is used by static
+# C++ constructors and destructors in the binary.
+# See http://www.codesourcery.com/public/cxx-abi/abi.html#dso-dtor
+#
+	.data
+        .align 4
+	.hidden __dso_handle
+        .globl __dso_handle
+__dso_handle:
+        .long __dso_handle
diff --git a/libc/private/logd.h b/libc/private/logd.h
index 43fa742..4a9b62e 100644
--- a/libc/private/logd.h
+++ b/libc/private/logd.h
@@ -44,6 +44,7 @@
     ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
 };
 
+int __libc_android_log_write(int prio, const char* tag, const char* buffer);
 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...);
 int __libc_android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap);
 
diff --git a/libc/stdio/vfscanf.c b/libc/stdio/vfscanf.c
index b16e3c7..78f404e 100644
--- a/libc/stdio/vfscanf.c
+++ b/libc/stdio/vfscanf.c
@@ -162,7 +162,13 @@
 			flags |= MAXINT;
 			goto again;
 		case 'L':
-			flags |= LONGDBL;
+			flags |=
+				(*fmt == 'd') ? LLONG :
+				(*fmt == 'i') ? LLONG :
+				(*fmt == 'o') ? LLONG :
+				(*fmt == 'u') ? LLONG :
+				(*fmt == 'x') ? LLONG :
+				LONGDBL;
 			goto again;
 		case 'h':
 			if (*fmt == 'h') {
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 4ba2177..f4bcab9 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -104,6 +104,7 @@
 	return (ret);
 }
 
+#ifdef CRT_LEGACY_WORKAROUND
 /*
  * Register a function to be performed at exit.
  */
@@ -112,6 +113,7 @@
 {
 	return (__cxa_atexit((void (*)(void *))func, NULL, NULL));
 }
+#endif
 
 /*
  * Call all handlers registered with __cxa_atexit() for the shared
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index ab713fb..a2cc3b3 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -407,9 +407,9 @@
                     tm = *t;
                     mkt = mktime64(&tm);
                     if (TYPE_SIGNED(time64_t))
-                        (void) sprintf(buf, "%lld",
+                        (void) snprintf(buf, sizeof(buf), "%lld",
                             (long long) mkt);
-                    else    (void) sprintf(buf, "%llu",
+                    else    (void) snprintf(buf, sizeof(buf), "%llu",
                             (unsigned long long) mkt);
                     pt = _add(buf, pt, ptlim, modifier);
                 }
diff --git a/libc/unistd/open.c b/libc/unistd/open.c
index e8b1c89..03cba45 100644
--- a/libc/unistd/open.c
+++ b/libc/unistd/open.c
@@ -35,9 +35,7 @@
 {
     mode_t  mode = 0;
 
-#if !defined(__i386__)
     flags |= O_LARGEFILE;
-#endif
 
     if (flags & O_CREAT)
     {
diff --git a/libc/unistd/openat.c b/libc/unistd/openat.c
index 88b39a4..6b7b367 100644
--- a/libc/unistd/openat.c
+++ b/libc/unistd/openat.c
@@ -35,9 +35,7 @@
 {
     mode_t  mode = 0;
 
-#if !defined(__i386__)
     flags |= O_LARGEFILE;
-#endif
 
     if (flags & O_CREAT)
     {
diff --git a/libc/unistd/sigblock.c b/libc/unistd/sigblock.c
index 863d7da..176bc13 100644
--- a/libc/unistd/sigblock.c
+++ b/libc/unistd/sigblock.c
@@ -37,6 +37,7 @@
         sigset_t  the_sigset;
     } in, out;
 
+    sigemptyset(&in.the_sigset);
     in.the_mask = mask;
 
     n = sigprocmask(SIG_BLOCK, &in.the_sigset, &out.the_sigset);
diff --git a/libc/unistd/sigsetmask.c b/libc/unistd/sigsetmask.c
index 4f46458..7842bf1 100644
--- a/libc/unistd/sigsetmask.c
+++ b/libc/unistd/sigsetmask.c
@@ -38,6 +38,7 @@
         sigset_t  the_sigset;
     } in, out;
 
+    sigemptyset(&in.the_sigset);
     in.the_mask = mask;
 
     n = sigprocmask(SIG_SETMASK, &in.the_sigset, &out.the_sigset);
diff --git a/libc/unistd/time.c b/libc/unistd/time.c
index 4b51675..18aa62c 100644
--- a/libc/unistd/time.c
+++ b/libc/unistd/time.c
@@ -34,12 +34,15 @@
 time(time_t *t)
 {
 	struct timeval tt;
+	time_t ret;
 
 	if (gettimeofday(&tt, (struct timezone *)0) < 0)
-		return (-1);
-	if (t)
-		*t = (time_t)tt.tv_sec;
-	return (tt.tv_sec);
+		ret = -1;
+	else
+		ret = tt.tv_sec;
+	if (t != NULL)
+		*t = ret;
+	return ret;
 }
 
 // return monotonically increasing CPU time in ticks relative to unspecified epoch
diff --git a/libc/zoneinfo/zoneinfo.dat b/libc/zoneinfo/zoneinfo.dat
index 7b1bd49..bac23f0 100644
--- a/libc/zoneinfo/zoneinfo.dat
+++ b/libc/zoneinfo/zoneinfo.dat
Binary files differ
diff --git a/libc/zoneinfo/zoneinfo.idx b/libc/zoneinfo/zoneinfo.idx
index 984aa00..7750e4d 100644
--- a/libc/zoneinfo/zoneinfo.idx
+++ b/libc/zoneinfo/zoneinfo.idx
Binary files differ
diff --git a/libc/zoneinfo/zoneinfo.version b/libc/zoneinfo/zoneinfo.version
index 2a4dffc..4abe0cc 100644
--- a/libc/zoneinfo/zoneinfo.version
+++ b/libc/zoneinfo/zoneinfo.version
@@ -1 +1 @@
-2011g
+2011h
diff --git a/libstdc++/src/new.cpp b/libstdc++/src/new.cpp
index a9c92d4..ddd3dba 100644
--- a/libstdc++/src/new.cpp
+++ b/libstdc++/src/new.cpp
@@ -7,7 +7,7 @@
 {
     void* p = malloc(size);
     if (p == NULL) {
-        // abort();
+        abort();
     }
     return p;
 }
@@ -16,7 +16,7 @@
 {
     void* p = malloc(size);
     if (p == NULL) {
-        // abort();
+        abort();
     }
     return p;
 }
diff --git a/libthread_db/Android.mk b/libthread_db/Android.mk
index 922b9cf..af506ed 100644
--- a/libthread_db/Android.mk
+++ b/libthread_db/Android.mk
@@ -22,12 +22,7 @@
 LOCAL_WHOLE_STATIC_LIBRARIES := libthread_db
 LOCAL_MODULE:=libthread_db
 LOCAL_SHARED_LIBRARIES := libdl libc
-
-# NOTE: Using --no-undefined results in a missing symbol that is defined inside
-# gdbserver and is resolved at runtime. Since there is no library containing
-# this symbol that we can link against, set LOCAL_ALLOW_UNDEFINED_SYMBOLS so
-# that --no-undefined is removed from the linker flags.
-LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
+LOCAL_ALLOW_UNDEFINED_SYMBOLS := false
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libthread_db/include/thread_db.h b/libthread_db/include/thread_db.h
index 6ff968f..1ed8ffca 100644
--- a/libthread_db/include/thread_db.h
+++ b/libthread_db/include/thread_db.h
@@ -149,6 +149,10 @@
 extern td_err_e td_ta_thr_iter(td_thragent_t const * agent, td_thr_iter_f * func, void * cookie,
                                td_thr_state_e state, int32_t prio, sigset_t * sigmask, uint32_t user_flags);
 
+extern td_err_e td_thr_event_enable(td_thrhandle_t const * handle, td_event_e event);
+
+extern td_err_e td_thr_get_info(td_thrhandle_t const * handle, td_thrinfo_t * info);
+
 extern char const ** td_symbol_list(void);
 
 extern td_err_e td_thr_tls_get_addr(const td_thrhandle_t * th,
diff --git a/libthread_db/libthread_db.c b/libthread_db/libthread_db.c
index 2cf4d38..86e1cf4 100644
--- a/libthread_db/libthread_db.c
+++ b/libthread_db/libthread_db.c
@@ -81,6 +81,25 @@
 {
     void * pc;
 
+#ifdef __i386__
+    /* Get the eip from offset 12*4 = 48 as defined in the struct
+     * user_regs_struct in user_32.h
+     */
+    pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)48 /* eip */, NULL);
+    /* FIXME - pc is a non-decremented breakpoint address, hence the
+     * addition of 1 on test.  This seems to work for the thread hook
+     * function in libc.so but should be properly fixed.
+     */
+    if (pc == ((int)bkpt_addr + 1)) {
+        /* The hook function takes the id of the new thread as it's first
+         * param, so grab it from ecx at offset 4 in struct user_regs_struct
+         * (using fastcall convention for x86)
+         */
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)4 /* ecx */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
+#else
     pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
 
     if (pc == bkpt_addr) {
@@ -90,6 +109,7 @@
         gEventMsgHandle.tid = gEventMsgHandle.pid;
         return 0x42;
     }
+#endif
     return 0;
 }
 
@@ -156,7 +176,7 @@
 {
     int32_t err;
 
-    /* 
+    /*
      * This is nasty, ps_pglobal_lookup is implemented in gdbserver and looks up
      * the symbol from it's cache, which is populated at start time with the
      * symbols returned from td_symbol_list via calls back to the host.
diff --git a/linker/Android.mk b/linker/Android.mk
index da311cd..e613397 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -50,6 +50,7 @@
 else
   ifeq ($(TARGET_ARCH),x86)
     LOCAL_CFLAGS += -DANDROID_X86_LINKER
+    LOCAL_CFLAGS += -I$(LOCAL_PATH)/../libc/arch-x86/bionic
   else
     ifeq ($(TARGET_ARCH),sh)
       LOCAL_CFLAGS += -DANDROID_SH_LINKER
diff --git a/linker/arch/x86/begin.S b/linker/arch/x86/begin.S
index b4427e0..5be59cb 100644
--- a/linker/arch/x86/begin.S
+++ b/linker/arch/x86/begin.S
@@ -44,3 +44,5 @@
         popl   %esp
         jmp    *%eax
 
+
+#include "__stack_chk_fail_local.S"
diff --git a/linker/linker.c b/linker/linker.c
index 5a9dccf..e350d89 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -822,7 +822,7 @@
 static int reserve_mem_region(soinfo *si)
 {
     void *base = mmap((void *)si->base, si->size, PROT_READ | PROT_EXEC,
-                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if (base == MAP_FAILED) {
         DL_ERR("%5d can NOT map (%sprelinked) library '%s' at 0x%08x "
               "as requested, will try general pool: %d (%s)",