merge from open-source master

Change-Id: I70266ee8c520b216773f267e46c8273d2334c31d
diff --git a/libc/Android.mk b/libc/Android.mk
index a6f2c83..d2e5e1f 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -343,6 +343,7 @@
 	arch-x86/bionic/setjmp.S \
 	arch-x86/bionic/_setjmp.S \
 	arch-x86/bionic/vfork.S \
+	arch-x86/bionic/syscall.S \
 	arch-x86/string/bzero.S \
 	arch-x86/string/memset.S \
 	arch-x86/string/memcmp.S \
diff --git a/libc/arch-x86/bionic/syscall.S b/libc/arch-x86/bionic/syscall.S
new file mode 100644
index 0000000..71abe6b
--- /dev/null
+++ b/libc/arch-x86/bionic/syscall.S
@@ -0,0 +1,52 @@
+/*
+ * Generic syscall call.
+ * Upon entry
+ *	%eax: system call number
+ *	%ebx: arg0 to system call
+ *	%ecx: arg..
+ *	%edx: arg..
+ *	%esi: arg..
+ *	%edi: arg..
+ * We push these (to save them) load them up with the
+ * values from the calling frame (not all will actually be valid)
+ * and make the syscall.
+ */
+
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type syscall, @function
+    .globl syscall
+    .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
+
+    int     $0x80
+
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    pop    %edi
+    pop    %esi
+    pop    %edx
+    pop    %ecx
+    pop    %ebx
+    pop    %eax
+    ret
diff --git a/libc/bionic/malloc_debug_leak.c b/libc/bionic/malloc_debug_leak.c
index e11606d..2ff8cee 100644
--- a/libc/bionic/malloc_debug_leak.c
+++ b/libc/bionic/malloc_debug_leak.c
@@ -430,8 +430,9 @@
     }
 
     if (new_buffer) {
-        size_t size = (bytes < old_bytes)?(bytes):(old_bytes);
-        memcpy(new_buffer, mem, size);
+        if (bytes > old_bytes)
+            bytes = old_bytes;
+        memcpy(new_buffer, mem, bytes);
         chk_free(mem);
     }
 
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 3294cea..6a2329f 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -601,13 +601,12 @@
 
     for (thread = gThreadList; thread != NULL; thread = thread->next)
         if (thread == (pthread_internal_t*)thid)
-            break;
+            goto FoundIt;
 
-    if (!thread) {
-        pthread_mutex_unlock(&gThreadListLock);
-        return ESRCH;
-    }
+    pthread_mutex_unlock(&gThreadListLock);
+    return ESRCH;
 
+FoundIt:
     if (thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) {
         pthread_mutex_unlock(&gThreadListLock);
         return EINVAL;
diff --git a/libc/bionic/pututline.c b/libc/bionic/pututline.c
index 2449068..c8427f7 100644
--- a/libc/bionic/pututline.c
+++ b/libc/bionic/pututline.c
@@ -34,7 +34,7 @@
 {
     FILE* f;
     struct utmp u;
-    int i;
+    long i;
 
     if (!(f = fopen(_PATH_UTMP, "w+")))
         return;
diff --git a/libc/bionic/ssp.c b/libc/bionic/ssp.c
index 20794f4..f83b2a4 100644
--- a/libc/bionic/ssp.c
+++ b/libc/bionic/ssp.c
@@ -76,9 +76,9 @@
     sigprocmask(SIG_BLOCK, &sigmask, NULL);
 
     /* Use /proc/self/exe link to obtain the program name for logging
-     * purposes. If it's not available, we set it to "unknown" */
+     * purposes. If it's not available, we set it to "<unknown>" */
     if ((count = readlink("/proc/self/exe", path, sizeof(path) - 1)) == -1) {
-        strlcpy(path, "unknown", sizeof(path));
+        strlcpy(path, "<unknown>", sizeof(path));
     } else {
         path[count] = '\0';
     }
diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h
index 9582796..f84d1d1 100644
--- a/libc/include/dlfcn.h
+++ b/libc/include/dlfcn.h
@@ -32,10 +32,22 @@
 
 __BEGIN_DECLS
 
+typedef struct {
+    const char *dli_fname;  /* Pathname of shared object that
+                               contains address */
+    void       *dli_fbase;  /* Address at which shared object
+                               is loaded */
+    const char *dli_sname;  /* Name of nearest symbol with address
+                               lower than addr */
+    void       *dli_saddr;  /* Exact address of symbol named
+                               in dli_sname */
+} Dl_info;
+
 extern void*        dlopen(const char*  filename, int flag);
 extern int          dlclose(void*  handle);
 extern const char*  dlerror(void);
 extern void*        dlsym(void*  handle, const char*  symbol);
+extern int          dladdr(void* addr, Dl_info *info);
 
 enum {
   RTLD_NOW  = 0,
diff --git a/libc/string/strcasecmp.c b/libc/string/strcasecmp.c
index 12f3a09..2be0913 100644
--- a/libc/string/strcasecmp.c
+++ b/libc/string/strcasecmp.c
@@ -98,8 +98,8 @@
 			if (cm[*us1] != cm[*us2++])
 				return (cm[*us1] - cm[*--us2]);
 			if (*us1++ == '\0')
-      break;
+				break;
 		} while (--n != 0);
-  }
+	}
 	return (0);
 }
diff --git a/libc/string/strchr.c b/libc/string/strchr.c
index e33694c..31ba4e2 100644
--- a/libc/string/strchr.c
+++ b/libc/string/strchr.c
@@ -38,6 +38,6 @@
 			return((char *)p);
 		if (!*p)
 			return((char *)NULL);
-  }
+	}
 	/* NOTREACHED */
 }
diff --git a/libc/string/strcoll.c b/libc/string/strcoll.c
index 365cad5..e3b1ec3 100755
--- a/libc/string/strcoll.c
+++ b/libc/string/strcoll.c
@@ -36,5 +36,5 @@
 int
 strcoll(const char *s1, const char *s2)
 {
-	return strcmp (s1, s2);
+	return strcmp(s1, s2);
 }
diff --git a/libc/string/strlcat.c b/libc/string/strlcat.c
index ad2215b..ceab094 100644
--- a/libc/string/strlcat.c
+++ b/libc/string/strlcat.c
@@ -46,9 +46,9 @@
 		if (n != 1) {
 			*d++ = *s;
 			n--;
-  }
+		}
 		s++;
-  }
+	}
 	*d = '\0';
 
 	return(dlen + (s - src));	/* count does not include NUL */
diff --git a/libc/string/strlcpy.c b/libc/string/strlcpy.c
index 38277eb..d32b659 100644
--- a/libc/string/strlcpy.c
+++ b/libc/string/strlcpy.c
@@ -37,7 +37,7 @@
 			if ((*d++ = *s++) == '\0')
 				break;
 		}
-  }
+	}
 
 	/* Not enough room in dst, add NUL and traverse rest of src */
 	if (n == 0) {
diff --git a/libc/string/strncat.c b/libc/string/strncat.c
index 1cb9405..c4df4f2 100644
--- a/libc/string/strncat.c
+++ b/libc/string/strncat.c
@@ -52,6 +52,6 @@
 			d++;
 		} while (--n != 0);
 		*d = 0;
-  }
+	}
 	return (dst);
 }
diff --git a/libc/string/strncmp.c b/libc/string/strncmp.c
index 9da41ab..1768808 100644
--- a/libc/string/strncmp.c
+++ b/libc/string/strncmp.c
@@ -38,14 +38,13 @@
 int
 strncmp(const char *s1, const char *s2, size_t n)
 {
-
 	if (n == 0)
 		return (0);
 	do {
 		if (*s1 != *s2++)
 			return (*(unsigned char *)s1 - *(unsigned char *)--s2);
 		if (*s1++ == 0)
-      break;
+			break;
 	} while (--n != 0);
 	return (0);
 }
diff --git a/libc/string/strncpy.c b/libc/string/strncpy.c
index b91091b..4426cbe 100644
--- a/libc/string/strncpy.c
+++ b/libc/string/strncpy.c
@@ -54,8 +54,8 @@
 				/* NUL pad the remaining n-1 bytes */
 				while (--n != 0)
 					*d++ = 0;
-      break;
-  }
+				break;
+			}
 		} while (--n != 0);
 	}
 	return (dst);
diff --git a/libc/string/strpbrk.c b/libc/string/strpbrk.c
index 6ba3796..cd3b71c 100644
--- a/libc/string/strpbrk.c
+++ b/libc/string/strpbrk.c
@@ -38,7 +38,7 @@
 {
 	const char *scanp;
 	int c, sc;
-  
+
 	while ((c = *s1++) != 0) {
 		for (scanp = s2; (sc = *scanp++) != 0;)
 			if (sc == c)
diff --git a/libc/string/strrchr.c b/libc/string/strrchr.c
index 2800781..4918f82 100644
--- a/libc/string/strrchr.c
+++ b/libc/string/strrchr.c
@@ -34,12 +34,12 @@
 strrchr(const char *p, int ch)
 {
 	char *save;
-  
+
 	for (save = NULL;; ++p) {
 		if (*p == ch)
 			save = (char *)p;
 		if (!*p)
 			return(save);
-  }
+	}
 	/* NOTREACHED */
 }
diff --git a/libc/string/strsep.c b/libc/string/strsep.c
index bcca681..c44bc5b 100644
--- a/libc/string/strsep.c
+++ b/libc/string/strsep.c
@@ -34,7 +34,7 @@
 
 /*
  * Get next token from string *stringp, where tokens are possibly-empty
- * strings separated by characters from delim.  
+ * strings separated by characters from delim.
  *
  * Writes NULs into the string at *stringp to end tokens.
  * delim need not remain constant from call to call.
diff --git a/libc/string/strstr.c b/libc/string/strstr.c
index debe96c..95a865b 100644
--- a/libc/string/strstr.c
+++ b/libc/string/strstr.c
@@ -51,6 +51,6 @@
 			} while (sc != c);
 		} while (strncmp(s, find, len) != 0);
 		s--;
-    }
+	}
 	return ((char *)s);
 }
diff --git a/libc/string/strxfrm.c b/libc/string/strxfrm.c
index f1843b5..3c4d707 100755
--- a/libc/string/strxfrm.c
+++ b/libc/string/strxfrm.c
@@ -29,7 +29,7 @@
 
 /*
  * Transform string s2 to string s1 using the current locale so that
- * strcmp of transformed strings yields the same result as strcoll. 
+ * strcmp of transformed strings yields the same result as strcoll.
  * Since Bionic really does not support locales, we assume we always use
  * the C locale.
  *
diff --git a/libc/unistd/pread.c b/libc/unistd/pread.c
index d2f71f7..b55623e 100644
--- a/libc/unistd/pread.c
+++ b/libc/unistd/pread.c
@@ -25,10 +25,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-extern int __pread64(int fd, void *buf, size_t nbytes, off_t lo, off_t hi);
+extern int __pread64(int fd, void *buf, size_t nbytes, loff_t offset);
 
 ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset)
 {
-    return __pread64(fd, buf, nbytes, offset, 0);
+    return __pread64(fd, buf, nbytes, offset);
 }
 
diff --git a/libc/unistd/pwrite.c b/libc/unistd/pwrite.c
index 5adf40a..ea080d2 100644
--- a/libc/unistd/pwrite.c
+++ b/libc/unistd/pwrite.c
@@ -28,10 +28,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-extern int __pwrite64(int fd, void *buf, size_t nbytes, off_t lo, off_t hi);
+extern int __pwrite64(int fd, void *buf, size_t nbytes, loff_t offset);
 
 ssize_t pwrite(int fd, void *buf, size_t nbytes, off_t offset)
 {
-    return __pwrite64(fd, buf, nbytes, offset, 0);
+    return __pwrite64(fd, buf, nbytes, offset);
 }
 
diff --git a/libdl/libdl.c b/libdl/libdl.c
index 7971942..b36af16 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+#include <dlfcn.h>
 /* These are stubs for functions that are actually defined
  * in the dynamic linker (dlfcn.c), and hijacked at runtime.
  */
 void *dlopen(const char *filename, int flag) { return 0; }
-char *dlerror(void) { return 0; }
+const char *dlerror(void) { return 0; }
 void *dlsym(void *handle, const char *symbol) { return 0; }
+int dladdr(void *addr, Dl_info *info) { return 0; }
 int dlclose(void *handle) { return 0; }
 
 #ifdef __arm__
diff --git a/libstdc++/src/new.cpp b/libstdc++/src/new.cpp
index 8189159..a9c92d4 100644
--- a/libstdc++/src/new.cpp
+++ b/libstdc++/src/new.cpp
@@ -23,16 +23,12 @@
 
 void  operator delete(void* ptr)
 {
-    if (ptr) {
-        free(ptr);
-    }
+    free(ptr);
 }
 
 void  operator delete[](void* ptr)
 {
-    if (ptr) {
-        free(ptr);
-    }
+    free(ptr);
 }
 
 void* operator new(std::size_t size, const std::nothrow_t&)
@@ -47,16 +43,12 @@
 
 void  operator delete(void* ptr, const std::nothrow_t&)
 {
-    if (ptr) {
-        free(ptr);
-    }
+    free(ptr);
 }
 
 void  operator delete[](void* ptr, const std::nothrow_t&)
 {
-    if (ptr) {
-        free(ptr);
-    }
+    free(ptr);
 }
 
 
diff --git a/linker/dlfcn.c b/linker/dlfcn.c
index bc6b95a..10ecb13 100644
--- a/linker/dlfcn.c
+++ b/linker/dlfcn.c
@@ -118,6 +118,37 @@
     return 0;
 }
 
+int dladdr(void *addr, Dl_info *info)
+{
+    int ret = 0;
+
+    pthread_mutex_lock(&dl_lock);
+
+    /* Determine if this address can be found in any library currently mapped */
+    soinfo *si = find_containing_library(addr);
+
+    if(si) {
+        memset(info, 0, sizeof(Dl_info));
+
+        info->dli_fname = si->name;
+        info->dli_fbase = (void*)si->base;
+
+        /* Determine if any symbol in the library contains the specified address */
+        Elf32_Sym *sym = find_containing_symbol(addr, si);
+
+        if(sym != NULL) {
+            info->dli_sname = si->strtab + sym->st_name;
+            info->dli_saddr = (void*)(si->base + sym->st_value);
+        }
+
+        ret = 1;
+    }
+
+    pthread_mutex_unlock(&dl_lock);
+
+    return ret;
+}
+
 int dlclose(void *handle)
 {
     pthread_mutex_lock(&dl_lock);
@@ -127,22 +158,22 @@
 }
 
 #if defined(ANDROID_ARM_LINKER)
-//                     0000000 00011111 111112 22222222 233333333334444444444
-//                     0123456 78901234 567890 12345678 901234567890123456789
+//                     0000000 00011111 111112 22222222 2333333 333344444444445555555
+//                     0123456 78901234 567890 12345678 9012345 678901234567890123456
 #define ANDROID_LIBDL_STRTAB \
-                      "dlopen\0dlclose\0dlsym\0dlerror\0dl_unwind_find_exidx\0"
+                      "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0"
 
 #elif defined(ANDROID_X86_LINKER)
-//                     0000000 00011111 111112 22222222 2333333333344444
-//                     0123456 78901234 567890 12345678 9012345678901234
+//                     0000000 00011111 111112 22222222 2333333 3333444444444455
+//                     0123456 78901234 567890 12345678 9012345 6789012345678901
 #define ANDROID_LIBDL_STRTAB \
-                      "dlopen\0dlclose\0dlsym\0dlerror\0dl_iterate_phdr\0"
+                      "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
 
 #elif defined(ANDROID_SH_LINKER)
-//                     0000000 00011111 111112 22222222 2333333333344444
-//                     0123456 78901234 567890 12345678 9012345678901234
+//                     0000000 00011111 111112 22222222 2333333 3333444444444455
+//                     0123456 78901234 567890 12345678 9012345 6789012345678901
 #define ANDROID_LIBDL_STRTAB \
-                      "dlopen\0dlclose\0dlsym\0dlerror\0dl_iterate_phdr\0"
+                      "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
 
 #else /* !defined(ANDROID_ARM_LINKER) && !defined(ANDROID_X86_LINKER) */
 #error Unsupported architecture. Only ARM and x86 are presently supported.
@@ -176,20 +207,25 @@
       st_info: STB_GLOBAL << 4,
       st_shndx: 1,
     },
-#ifdef ANDROID_ARM_LINKER
     { st_name: 29,
+      st_value: (Elf32_Addr) &dladdr,
+      st_info: STB_GLOBAL << 4,
+      st_shndx: 1,
+    },
+#ifdef ANDROID_ARM_LINKER
+    { st_name: 36,
       st_value: (Elf32_Addr) &dl_unwind_find_exidx,
       st_info: STB_GLOBAL << 4,
       st_shndx: 1,
     },
 #elif defined(ANDROID_X86_LINKER)
-    { st_name: 29,
+    { st_name: 36,
       st_value: (Elf32_Addr) &dl_iterate_phdr,
       st_info: STB_GLOBAL << 4,
       st_shndx: 1,
     },
 #elif defined(ANDROID_SH_LINKER)
-    { st_name: 29,
+    { st_name: 36,
       st_value: (Elf32_Addr) &dl_iterate_phdr,
       st_info: STB_GLOBAL << 4,
       st_shndx: 1,
@@ -217,7 +253,7 @@
  * stubbing them out in libdl.
  */
 static unsigned libdl_buckets[1] = { 1 };
-static unsigned libdl_chains[6] = { 0, 2, 3, 4, 5, 0 };
+static unsigned libdl_chains[7] = { 0, 2, 3, 4, 5, 6, 0 };
 
 soinfo libdl_info = {
     name: "libdl.so",
@@ -227,7 +263,7 @@
     symtab: libdl_symtab,
 
     nbucket: 1,
-    nchain: 6,
+    nchain: 7,
     bucket: libdl_buckets,
     chain: libdl_chains,
 };
diff --git a/linker/linker.c b/linker/linker.c
index 7eb1ef9..5cc05e2 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -535,6 +535,40 @@
     return NULL;
 }
 
+soinfo *find_containing_library(void *addr)
+{
+    soinfo *si;
+
+    for(si = solist; si != NULL; si = si->next)
+    {
+        if((unsigned)addr >= si->base && (unsigned)addr - si->base < si->size) {
+            return si;
+        }
+    }
+
+    return NULL;
+}
+
+Elf32_Sym *find_containing_symbol(void *addr, soinfo *si)
+{
+    unsigned int i;
+    unsigned soaddr = (unsigned)addr - si->base;
+
+    /* Search the library's symbol table for any defined symbol which
+     * contains this address */
+    for(i=0; i<si->nchain; i++) {
+        Elf32_Sym *sym = &si->symtab[i];
+
+        if(sym->st_shndx != SHN_UNDEF &&
+           soaddr >= sym->st_value &&
+           soaddr < sym->st_value + sym->st_size) {
+            return sym;
+        }
+    }
+
+    return NULL;
+}
+
 #if 0
 static void dump(soinfo *si)
 {
diff --git a/linker/linker.h b/linker/linker.h
index ec01489..8cd56b0 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -225,6 +225,8 @@
 unsigned unload_library(soinfo *si);
 Elf32_Sym *lookup_in_library(soinfo *si, const char *name);
 Elf32_Sym *lookup(const char *name, soinfo **found);
+soinfo *find_containing_library(void *addr);
+Elf32_Sym *find_containing_symbol(void *addr, soinfo *si);
 const char *linker_get_error(void);
 
 #ifdef ANDROID_ARM_LINKER