Merge "Add getgrgid_r/getgrnam_r."
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 151749b..f81b89f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -333,7 +333,7 @@
 int     __set_thread_area:set_thread_area(void*) x86
 
 # vdso stuff.
-int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64,x86
-int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
-int gettimeofday(timeval*, timezone*)                   arm,mips,mips64,x86
-int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86_64
+int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64
+int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86,x86_64
+int gettimeofday(timeval*, timezone*)                   arm,mips,mips64
+int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86,x86_64
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 6ef81bb..d72a160 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -39,7 +39,6 @@
     arch-arm/bionic/__bionic_clone.S \
     arch-arm/bionic/_exit_with_stack_teardown.S \
     arch-arm/bionic/libgcc_compat.c \
-    arch-arm/bionic/libgcc_protect_unwind.c \
     arch-arm/bionic/__restore.S \
     arch-arm/bionic/setjmp.S \
     arch-arm/bionic/syscall.S \
diff --git a/libc/arch-arm/bionic/libgcc_protect_unwind.c b/libc/arch-arm/bionic/libgcc_protect_unwind.c
deleted file mode 100644
index 6d758fc..0000000
--- a/libc/arch-arm/bionic/libgcc_protect_unwind.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// TODO: This file should go away once unwinder migration to libc++.so is complete.
-
-extern char _Unwind_Backtrace __attribute((visibility("protected")));
-extern char __gnu_Unwind_Find_exidx __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_VFP_D __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_VFP __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_VFP_D_16_to_31 __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_WMMXD __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_WMMXC __attribute((visibility("protected")));
-extern char _Unwind_GetCFA __attribute((visibility("protected")));
-extern char __gnu_Unwind_RaiseException __attribute((visibility("protected")));
-extern char __gnu_Unwind_ForcedUnwind __attribute((visibility("protected")));
-extern char __gnu_Unwind_Resume __attribute((visibility("protected")));
-extern char __gnu_Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
-extern char _Unwind_Complete __attribute((visibility("protected")));
-extern char _Unwind_DeleteException __attribute((visibility("protected")));
-extern char _Unwind_VRS_Get __attribute((visibility("protected")));
-extern char _Unwind_VRS_Set __attribute((visibility("protected")));
-extern char __gnu_Unwind_Backtrace __attribute((visibility("protected")));
-extern char _Unwind_VRS_Pop __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_VFP_D __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_VFP __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_VFP_D_16_to_31 __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_WMMXD __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_WMMXC __attribute((visibility("protected")));
-extern char ___Unwind_RaiseException __attribute((visibility("protected")));
-extern char _Unwind_RaiseException __attribute((visibility("protected")));
-extern char ___Unwind_Resume __attribute((visibility("protected")));
-extern char _Unwind_Resume __attribute((visibility("protected")));
-extern char ___Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
-extern char _Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
-extern char ___Unwind_ForcedUnwind __attribute((visibility("protected")));
-extern char _Unwind_ForcedUnwind __attribute((visibility("protected")));
-extern char ___Unwind_Backtrace __attribute((visibility("protected")));
-extern char _Unwind_GetRegionStart __attribute((visibility("protected")));
-extern char _Unwind_GetLanguageSpecificData __attribute((visibility("protected")));
-extern char _Unwind_GetDataRelBase __attribute((visibility("protected")));
-extern char _Unwind_GetTextRelBase __attribute((visibility("protected")));
-
-void* __bionic_libgcc_unwind_symbols[] = {
-    &_Unwind_Backtrace,
-    &__gnu_Unwind_Find_exidx,
-    &__gnu_Unwind_Restore_VFP_D,
-    &__gnu_Unwind_Restore_VFP,
-    &__gnu_Unwind_Restore_VFP_D_16_to_31,
-    &__gnu_Unwind_Restore_WMMXD,
-    &__gnu_Unwind_Restore_WMMXC,
-    &_Unwind_GetCFA,
-    &__gnu_Unwind_RaiseException,
-    &__gnu_Unwind_ForcedUnwind,
-    &__gnu_Unwind_Resume,
-    &__gnu_Unwind_Resume_or_Rethrow,
-    &_Unwind_Complete,
-    &_Unwind_DeleteException,
-    &_Unwind_VRS_Get,
-    &_Unwind_VRS_Set,
-    &__gnu_Unwind_Backtrace,
-    &_Unwind_VRS_Pop,
-    &__gnu_Unwind_Save_VFP_D,
-    &__gnu_Unwind_Save_VFP,
-    &__gnu_Unwind_Save_VFP_D_16_to_31,
-    &__gnu_Unwind_Save_WMMXD,
-    &__gnu_Unwind_Save_WMMXC,
-    &___Unwind_RaiseException,
-    &_Unwind_RaiseException,
-    &___Unwind_Resume,
-    &_Unwind_Resume,
-    &___Unwind_Resume_or_Rethrow,
-    &_Unwind_Resume_or_Rethrow,
-    &___Unwind_ForcedUnwind,
-    &_Unwind_ForcedUnwind,
-    &___Unwind_Backtrace,
-    &_Unwind_GetRegionStart,
-    &_Unwind_GetLanguageSpecificData,
-    &_Unwind_GetDataRelBase,
-    &_Unwind_GetTextRelBase,
-};
diff --git a/libc/arch-x86/syscalls/clock_gettime.S b/libc/arch-x86/syscalls/__clock_gettime.S
similarity index 92%
rename from libc/arch-x86/syscalls/clock_gettime.S
rename to libc/arch-x86/syscalls/__clock_gettime.S
index 0875cfb..61eadc8 100644
--- a/libc/arch-x86/syscalls/clock_gettime.S
+++ b/libc/arch-x86/syscalls/__clock_gettime.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(clock_gettime)
+ENTRY(__clock_gettime)
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
@@ -23,4 +23,4 @@
     popl    %ecx
     popl    %ebx
     ret
-END(clock_gettime)
+END(__clock_gettime)
diff --git a/libc/arch-x86/syscalls/gettimeofday.S b/libc/arch-x86/syscalls/__gettimeofday.S
similarity index 92%
rename from libc/arch-x86/syscalls/gettimeofday.S
rename to libc/arch-x86/syscalls/__gettimeofday.S
index a508c14..90f3f91 100644
--- a/libc/arch-x86/syscalls/gettimeofday.S
+++ b/libc/arch-x86/syscalls/__gettimeofday.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(gettimeofday)
+ENTRY(__gettimeofday)
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
@@ -23,4 +23,4 @@
     popl    %ecx
     popl    %ebx
     ret
-END(gettimeofday)
+END(__gettimeofday)
diff --git a/libc/bionic/debug_mapinfo.cpp b/libc/bionic/debug_mapinfo.cpp
index 698ab6b..de72cb2 100644
--- a/libc/bionic/debug_mapinfo.cpp
+++ b/libc/bionic/debug_mapinfo.cpp
@@ -27,6 +27,7 @@
  */
 
 #include <ctype.h>
+#include <elf.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <string.h>
@@ -35,14 +36,22 @@
 #include "debug_mapinfo.h"
 #include "malloc_debug_disable.h"
 
+#if defined(__LP64__)
+#define Elf_W(x) Elf64_##x
+#else
+#define Elf_W(x) Elf32_##x
+#endif
+
 // Format of /proc/<PID>/maps:
 //   6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so
 static mapinfo_t* parse_maps_line(char* line) {
   uintptr_t start;
   uintptr_t end;
+  uintptr_t offset;
+  char permissions[4];
   int name_pos;
-  if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
-             &end, &name_pos) < 2) {
+  if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d%n", &start,
+             &end, permissions, &offset, &name_pos) < 2) {
     return NULL;
   }
 
@@ -59,6 +68,14 @@
   if (mi) {
     mi->start = start;
     mi->end = end;
+    mi->offset = offset;
+    if (permissions[0] != 'r') {
+      // Any unreadable map will just get a zero load base.
+      mi->load_base = 0;
+      mi->load_base_read = true;
+    } else {
+      mi->load_base_read = false;
+    }
     memcpy(mi->name, name, name_len);
     mi->name[name_len] = '\0';
   }
@@ -95,11 +112,58 @@
   }
 }
 
+template<typename T>
+static inline bool get_val(mapinfo_t* mi, uintptr_t addr, T* store) {
+  if (addr < mi->start || addr + sizeof(T) > mi->end) {
+    return false;
+  }
+  // Make sure the address is aligned properly.
+  if (addr & (sizeof(T)-1)) {
+    return false;
+  }
+  *store = *reinterpret_cast<T*>(addr);
+  return true;
+}
+
+__LIBC_HIDDEN__ void mapinfo_read_loadbase(mapinfo_t* mi) {
+  mi->load_base = 0;
+  mi->load_base_read = true;
+  uintptr_t addr = mi->start;
+  Elf_W(Ehdr) ehdr;
+  if (!get_val<Elf_W(Half)>(mi, addr + offsetof(Elf_W(Ehdr), e_phnum), &ehdr.e_phnum)) {
+    return;
+  }
+  if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Ehdr), e_phoff), &ehdr.e_phoff)) {
+    return;
+  }
+  addr += ehdr.e_phoff;
+  for (size_t i = 0; i < ehdr.e_phnum; i++) {
+    Elf_W(Phdr) phdr;
+    if (!get_val<Elf_W(Word)>(mi, addr + offsetof(Elf_W(Phdr), p_type), &phdr.p_type)) {
+      return;
+    }
+    if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Phdr), p_offset), &phdr.p_offset)) {
+      return;
+    }
+    if (phdr.p_type == PT_LOAD && phdr.p_offset == mi->offset) {
+      if (!get_val<Elf_W(Addr)>(mi, addr + offsetof(Elf_W(Phdr), p_vaddr), &phdr.p_vaddr)) {
+        return;
+      }
+      mi->load_base = phdr.p_vaddr;
+      return;
+    }
+    addr += sizeof(phdr);
+  }
+}
+
 // Find the containing map info for the PC.
 __LIBC_HIDDEN__ const mapinfo_t* mapinfo_find(mapinfo_t* mi, uintptr_t pc, uintptr_t* rel_pc) {
   for (; mi != NULL; mi = mi->next) {
     if ((pc >= mi->start) && (pc < mi->end)) {
-      *rel_pc = pc - mi->start;
+      if (!mi->load_base_read) {
+        mapinfo_read_loadbase(mi);
+      }
+      *rel_pc = pc - mi->start + mi->load_base;
       return mi;
     }
   }
diff --git a/libc/bionic/debug_mapinfo.h b/libc/bionic/debug_mapinfo.h
index 926b377..af7d05d 100644
--- a/libc/bionic/debug_mapinfo.h
+++ b/libc/bionic/debug_mapinfo.h
@@ -35,6 +35,9 @@
   struct mapinfo_t* next;
   uintptr_t start;
   uintptr_t end;
+  uintptr_t offset;
+  uintptr_t load_base;
+  bool load_base_read;
   char name[];
 };
 
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index bd71628..3ca6c0d 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -64,18 +64,15 @@
 // Declared in "private/bionic_ssp.h".
 uintptr_t __stack_chk_guard = 0;
 
-/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
- * in memory. Beware: all writes to libc globals from this function will
- * apply to linker-private copies and will not be visible from libc later on.
- *
- * Note: this function creates a pthread_internal_t for the initial thread and
- * stores the pointer in TLS, but does not add it to pthread's thread list. This
- * has to be done later from libc itself (see __libc_init_common).
- *
- * This function also stores a pointer to the kernel argument block in a TLS slot to be
- * picked up by the libc constructor.
- */
-void __libc_init_tls(KernelArgumentBlock& args) {
+// Setup for the main thread. For dynamic executables, this is called by the
+// linker _before_ libc is mapped in memory. This means that all writes to
+// globals from this function will apply to linker-private copies and will not
+// be visible from libc later on.
+//
+// Note: this function creates a pthread_internal_t for the initial thread and
+// stores the pointer in TLS, but does not add it to pthread's thread list. This
+// has to be done later from libc itself (see __libc_init_common).
+void __libc_init_main_thread(KernelArgumentBlock& args) {
   __libc_auxv = args.auxv;
 
   static pthread_internal_t main_thread;
@@ -99,6 +96,9 @@
   __init_thread(&main_thread);
   __init_tls(&main_thread);
   __set_tls(main_thread.tls);
+
+  // Store a pointer to the kernel argument block in a TLS slot to be
+  // picked up by the libc constructor.
   main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
 
   __init_alternate_signal_stack(&main_thread);
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 7794fbe..ef57af6 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -90,7 +90,7 @@
                             int (*slingshot)(int, char**, char**),
                             structors_array_t const * const structors) {
   KernelArgumentBlock args(raw_args);
-  __libc_init_tls(args);
+  __libc_init_main_thread(args);
   __libc_init_AT_SECURE(args);
   __libc_init_common(args);
 
diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp
index a240663..9eae3d5 100644
--- a/libc/bionic/vdso.cpp
+++ b/libc/bionic/vdso.cpp
@@ -19,19 +19,24 @@
 #include <sys/auxv.h>
 #include <unistd.h>
 
-// x86 has a vdso, but there's nothing useful to us in it.
-#if defined(__aarch64__) || defined(__x86_64__)
+#if defined(__aarch64__) || defined(__x86_64__) || defined (__i386__)
 
 #if defined(__aarch64__)
 #define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
 #define VDSO_GETTIMEOFDAY_SYMBOL  "__kernel_gettimeofday"
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__i386__)
 #define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
 #define VDSO_GETTIMEOFDAY_SYMBOL  "__vdso_gettimeofday"
 #endif
 
+#include <errno.h>
+#include <limits.h>
+#include <sys/mman.h>
 #include <time.h>
 
+#include "private/bionic_prctl.h"
+#include "private/libc_logging.h"
+
 extern "C" int __clock_gettime(int, timespec*);
 extern "C" int __gettimeofday(timeval*, struct timezone*);
 
@@ -46,28 +51,31 @@
   VDSO_END
 };
 
-static vdso_entry vdso_entries[] = {
+static union {
+  vdso_entry entries[VDSO_END];
+  char padding[PAGE_SIZE];
+} vdso __attribute__((aligned(PAGE_SIZE))) = {{
   [VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) },
   [VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
-};
+}};
 
 int clock_gettime(int clock_id, timespec* tp) {
-  static int (*vdso_clock_gettime)(int, timespec*) =
-      reinterpret_cast<int (*)(int, timespec*)>(vdso_entries[VDSO_CLOCK_GETTIME].fn);
+  int (*vdso_clock_gettime)(int, timespec*) =
+      reinterpret_cast<int (*)(int, timespec*)>(vdso.entries[VDSO_CLOCK_GETTIME].fn);
   return vdso_clock_gettime(clock_id, tp);
 }
 
 int gettimeofday(timeval* tv, struct timezone* tz) {
-  static int (*vdso_gettimeofday)(timeval*, struct timezone*) =
-      reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso_entries[VDSO_GETTIMEOFDAY].fn);
+  int (*vdso_gettimeofday)(timeval*, struct timezone*) =
+      reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso.entries[VDSO_GETTIMEOFDAY].fn);
   return vdso_gettimeofday(tv, tz);
 }
 
-void __libc_init_vdso() {
+static void __libc_init_vdso_entries() {
   // Do we have a vdso?
   uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
   ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
-  if (vdso_ehdr == NULL) {
+  if (vdso_ehdr == nullptr) {
     return;
   }
 
@@ -85,7 +93,7 @@
 
   // Where's the dynamic table?
   ElfW(Addr) vdso_addr = 0;
-  ElfW(Dyn)* vdso_dyn = NULL;
+  ElfW(Dyn)* vdso_dyn = nullptr;
   ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
   for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
     if (vdso_phdr[i].p_type == PT_DYNAMIC) {
@@ -94,13 +102,13 @@
       vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
     }
   }
-  if (vdso_addr == 0 || vdso_dyn == NULL) {
+  if (vdso_addr == 0 || vdso_dyn == nullptr) {
     return;
   }
 
   // Where are the string and symbol tables?
-  const char* strtab = NULL;
-  ElfW(Sym)* symtab = NULL;
+  const char* strtab = nullptr;
+  ElfW(Sym)* symtab = nullptr;
   for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
     if (d->d_tag == DT_STRTAB) {
       strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr);
@@ -108,20 +116,31 @@
       symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr);
     }
   }
-  if (strtab == NULL || symtab == NULL) {
+  if (strtab == nullptr || symtab == nullptr) {
     return;
   }
 
   // Are there any symbols we want?
   for (size_t i = 0; i < symbol_count; ++i) {
     for (size_t j = 0; j < VDSO_END; ++j) {
-      if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) {
-        vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
+      if (strcmp(vdso.entries[j].name, strtab + symtab[i].st_name) == 0) {
+        vdso.entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
       }
     }
   }
 }
 
+void __libc_init_vdso() {
+  __libc_init_vdso_entries();
+
+  // We can't use PR_SET_VMA because this isn't an anonymous region.
+  // Long-term we should be able to replace all of this with ifuncs.
+  static_assert(PAGE_SIZE == sizeof(vdso), "sizeof(vdso) too large");
+  if (mprotect(vdso.entries, sizeof(vdso), PROT_READ) == -1) {
+    __libc_fatal("failed to mprotect PROT_READ vdso function pointer table: %s", strerror(errno));
+  }
+}
+
 #else
 
 void __libc_init_vdso() {
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 30dc0eb..d92d9d9 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -114,7 +114,7 @@
 
 #if defined(__cplusplus)
 class KernelArgumentBlock;
-extern __LIBC_HIDDEN__ void __libc_init_tls(KernelArgumentBlock& args);
+extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock& args);
 #endif
 
 #endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 73eeba1..0718efc 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3465,7 +3465,7 @@
     _exit(EXIT_FAILURE);
   }
 
-  __libc_init_tls(args);
+  __libc_init_main_thread(args);
 
   // Initialize the linker's own global variables
   linker_so.call_constructors();
diff --git a/tests/Android.mk b/tests/Android.mk
index 4d9a136..21deb5c 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -408,7 +408,7 @@
 
 LOCAL_CXX = $(LOCAL_PATH)/file-check-cxx \
     $(HOST_OUT_EXECUTABLES)/FileCheck \
-    $($(LOCAL_2ND_ARCH_VAR_PREFIX)CXX_BARE) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CXX) \
     GCC \
 
 LOCAL_CLANG := false