Merge "Export some symbols for vendor libmemunreachable"
diff --git a/libc/Android.bp b/libc/Android.bp
index 1da7262..57d4039 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1582,12 +1582,6 @@
         "tz_version", // Version metadata for tzdata to help debugging.
     ],
 
-    // Leave the symbols in the shared library so that stack unwinders can produce
-    // meaningful name resolution.
-    strip: {
-        keep_symbols: true,
-    },
-
     // Do not pack libc.so relocations; see http://b/20645321 for details.
     pack_relocations: false,
 
@@ -1628,9 +1622,23 @@
             static: {
                 srcs: [":libc_sources_static_arm"],
             },
+
+            // Arm 32 bit does not produce complete exidx unwind information
+            // so keep the .debug_frame which is relatively small and does
+            // include needed unwind information.
+            // See b/132992102 for details.
+            strip: {
+                keep_symbols_and_debug_frame: true,
+            },
         },
         arm64: {
             version_script: ":libc.arm64.map",
+
+            // Leave the symbols in the shared library so that stack unwinders can produce
+            // meaningful name resolution.
+            strip: {
+                keep_symbols: true,
+            },
         },
         x86: {
             // TODO: This is to work around b/24465209. Remove after root cause is fixed.
@@ -1638,9 +1646,21 @@
             ldflags: ["-Wl,--hash-style=both"],
 
             version_script: ":libc.x86.map",
+
+            // Leave the symbols in the shared library so that stack unwinders can produce
+            // meaningful name resolution.
+            strip: {
+                keep_symbols: true,
+            },
         },
         x86_64: {
             version_script: ":libc.x86_64.map",
+
+            // Leave the symbols in the shared library so that stack unwinders can produce
+            // meaningful name resolution.
+            strip: {
+                keep_symbols: true,
+            },
         },
     },
 
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index c6e09a2..bd5c27d 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -58,85 +58,31 @@
 // functions to share state, but <grp.h> functions can't clobber <passwd.h>
 // functions' state and vice versa.
 #include "bionic/pthread_internal.h"
-static group_state_t* get_group_tls_buffer() {
-  return &__get_bionic_tls().group;
-}
-
-static passwd_state_t* get_passwd_tls_buffer() {
-  return &__get_bionic_tls().passwd;
-}
 
 static void init_group_state(group_state_t* state) {
   memset(state, 0, sizeof(group_state_t) - sizeof(state->getgrent_idx));
+  state->group_.gr_name = state->group_name_buffer_;
   state->group_.gr_mem = state->group_members_;
+  state->group_.gr_mem[0] = state->group_.gr_name;
 }
 
-static group_state_t* __group_state() {
-  group_state_t* result = get_group_tls_buffer();
-  if (result != nullptr) {
-    init_group_state(result);
-  }
+static group_state_t* get_group_tls_buffer() {
+  auto result = &__get_bionic_tls().group;
+  init_group_state(result);
   return result;
 }
 
-static int do_getpw_r(int by_name, const char* name, uid_t uid,
-                      passwd* dst, char* buf, size_t byte_count,
-                      passwd** result) {
-  // getpwnam_r and getpwuid_r don't modify errno, but library calls we
-  // make might.
-  ErrnoRestorer errno_restorer;
-  *result = nullptr;
-
-  // Our implementation of getpwnam(3) and getpwuid(3) use thread-local
-  // storage, so we can call them as long as we copy everything out
-  // before returning.
-  const passwd* src = by_name ? getpwnam(name) : getpwuid(uid); // NOLINT: see above.
-
-  // POSIX allows failure to find a match to be considered a non-error.
-  // Reporting success (0) but with *result NULL is glibc's behavior.
-  if (src == nullptr) {
-    return (errno == ENOENT) ? 0 : errno;
-  }
-
-  // Work out where our strings will go in 'buf', and whether we've got
-  // enough space.
-  size_t required_byte_count = 0;
-  dst->pw_name = buf;
-  required_byte_count += strlen(src->pw_name) + 1;
-  dst->pw_dir = buf + required_byte_count;
-  required_byte_count += strlen(src->pw_dir) + 1;
-  dst->pw_shell = buf + required_byte_count;
-  required_byte_count += strlen(src->pw_shell) + 1;
-  if (byte_count < required_byte_count) {
-    return ERANGE;
-  }
-
-  // Copy the strings.
-  snprintf(buf, byte_count, "%s%c%s%c%s", src->pw_name, 0, src->pw_dir, 0, src->pw_shell);
-
-  // pw_passwd and pw_gecos are non-POSIX and unused (always NULL) in bionic.
-  // Note: On LP32, we define pw_gecos to pw_passwd since they're both NULL.
-  dst->pw_passwd = nullptr;
-#if defined(__LP64__)
-  dst->pw_gecos = nullptr;
-#endif
-
-  // Copy the integral fields.
-  dst->pw_gid = src->pw_gid;
-  dst->pw_uid = src->pw_uid;
-
-  *result = dst;
-  return 0;
+static void init_passwd_state(passwd_state_t* state) {
+  memset(state, 0, sizeof(passwd_state_t) - sizeof(state->getpwent_idx));
+  state->passwd_.pw_name = state->name_buffer_;
+  state->passwd_.pw_dir = state->dir_buffer_;
+  state->passwd_.pw_shell = state->sh_buffer_;
 }
 
-int getpwnam_r(const char* name, passwd* pwd,
-               char* buf, size_t byte_count, passwd** result) {
-  return do_getpw_r(1, name, -1, pwd, buf, byte_count, result);
-}
-
-int getpwuid_r(uid_t uid, passwd* pwd,
-               char* buf, size_t byte_count, passwd** result) {
-  return do_getpw_r(0, nullptr, uid, pwd, buf, byte_count, result);
+static passwd_state_t* get_passwd_tls_buffer() {
+  auto result = &__get_bionic_tls().passwd;
+  init_passwd_state(result);
+  return result;
 }
 
 static passwd* android_iinfo_to_passwd(passwd_state_t* state,
@@ -146,11 +92,8 @@
   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
 
   passwd* pw = &state->passwd_;
-  pw->pw_name  = state->name_buffer_;
   pw->pw_uid   = iinfo->aid;
   pw->pw_gid   = iinfo->aid;
-  pw->pw_dir   = state->dir_buffer_;
-  pw->pw_shell = state->sh_buffer_;
   return pw;
 }
 
@@ -159,9 +102,7 @@
   snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), "%s", iinfo->name);
 
   group* gr = &state->group_;
-  gr->gr_name   = state->group_name_buffer_;
-  gr->gr_gid    = iinfo->aid;
-  gr->gr_mem[0] = gr->gr_name;
+  gr->gr_gid = iinfo->aid;
   return gr;
 }
 
@@ -435,9 +376,6 @@
   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/vendor/bin/sh");
 
   passwd* pw = &state->passwd_;
-  pw->pw_name  = state->name_buffer_;
-  pw->pw_dir   = state->dir_buffer_;
-  pw->pw_shell = state->sh_buffer_;
   pw->pw_uid   = uid;
   pw->pw_gid   = uid;
   return pw;
@@ -456,9 +394,7 @@
            "oem_%u", gid);
 
   group* gr = &state->group_;
-  gr->gr_name   = state->group_name_buffer_;
-  gr->gr_gid    = gid;
-  gr->gr_mem[0] = gr->gr_name;
+  gr->gr_gid = gid;
   return gr;
 }
 
@@ -486,9 +422,6 @@
   snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
 
   passwd* pw = &state->passwd_;
-  pw->pw_name  = state->name_buffer_;
-  pw->pw_dir   = state->dir_buffer_;
-  pw->pw_shell = state->sh_buffer_;
   pw->pw_uid   = uid;
   pw->pw_gid   = uid;
   return pw;
@@ -505,18 +438,11 @@
   print_app_name_from_gid(gid, state->group_name_buffer_, sizeof(state->group_name_buffer_));
 
   group* gr = &state->group_;
-  gr->gr_name   = state->group_name_buffer_;
-  gr->gr_gid    = gid;
-  gr->gr_mem[0] = gr->gr_name;
+  gr->gr_gid = gid;
   return gr;
 }
 
-passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function.
-  passwd_state_t* state = get_passwd_tls_buffer();
-  if (state == nullptr) {
-    return nullptr;
-  }
-
+passwd* getpwuid_internal(uid_t uid, passwd_state_t* state) {
   if (auto* android_id_info = find_android_id_info(uid); android_id_info != nullptr) {
     return android_iinfo_to_passwd(state, android_id_info);
   }
@@ -529,12 +455,12 @@
   return app_id_to_passwd(uid, state);
 }
 
-passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
+passwd* getpwuid(uid_t uid) {  // NOLINT: implementing bad function.
   passwd_state_t* state = get_passwd_tls_buffer();
-  if (state == nullptr) {
-    return nullptr;
-  }
+  return getpwuid_internal(uid, state);
+}
 
+passwd* getpwnam_internal(const char* login, passwd_state_t* state) {
   if (auto* android_id_info = find_android_id_info(login); android_id_info != nullptr) {
     return android_iinfo_to_passwd(state, android_id_info);
   }
@@ -553,6 +479,39 @@
   return app_id_to_passwd(app_id_from_name(login, false), state);
 }
 
+passwd* getpwnam(const char* login) {  // NOLINT: implementing bad function.
+  passwd_state_t* state = get_passwd_tls_buffer();
+  return getpwnam_internal(login, state);
+}
+
+static int getpasswd_r(bool by_name, const char* name, uid_t uid, struct passwd* pwd, char* buf,
+                       size_t buflen, struct passwd** result) {
+  ErrnoRestorer errno_restorer;
+  *result = nullptr;
+  char* p =
+      reinterpret_cast<char*>(__BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
+  if (p + sizeof(passwd_state_t) > buf + buflen) {
+    return ERANGE;
+  }
+  passwd_state_t* state = reinterpret_cast<passwd_state_t*>(p);
+  init_passwd_state(state);
+  passwd* retval = (by_name ? getpwnam_internal(name, state) : getpwuid_internal(uid, state));
+  if (retval != nullptr) {
+    *pwd = *retval;
+    *result = pwd;
+    return 0;
+  }
+  return errno;
+}
+
+int getpwnam_r(const char* name, passwd* pwd, char* buf, size_t byte_count, passwd** result) {
+  return getpasswd_r(true, name, -1, pwd, buf, byte_count, result);
+}
+
+int getpwuid_r(uid_t uid, passwd* pwd, char* buf, size_t byte_count, passwd** result) {
+  return getpasswd_r(false, nullptr, uid, pwd, buf, byte_count, result);
+}
+
 // All users are in just one group, the one passed in.
 int getgrouplist(const char* /*user*/, gid_t group, gid_t* groups, int* ngroups) {
   if (*ngroups < 1) {
@@ -590,9 +549,6 @@
 
 passwd* getpwent() {
   passwd_state_t* state = get_passwd_tls_buffer();
-  if (state == nullptr) {
-    return nullptr;
-  }
   if (state->getpwent_idx < 0) {
     return nullptr;
   }
@@ -643,10 +599,7 @@
 }
 
 group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
-  group_state_t* state = __group_state();
-  if (state == nullptr) {
-    return nullptr;
-  }
+  group_state_t* state = get_group_tls_buffer();
   return getgrgid_internal(gid, state);
 }
 
@@ -670,10 +623,7 @@
 }
 
 group* getgrnam(const char* name) { // NOLINT: implementing bad function.
-  group_state_t* state = __group_state();
-  if (state == nullptr) {
-    return nullptr;
-  }
+  group_state_t* state = get_group_tls_buffer();
   return getgrnam_internal(name, state);
 }
 
@@ -719,9 +669,6 @@
 
 group* getgrent() {
   group_state_t* state = get_group_tls_buffer();
-  if (state == nullptr) {
-    return nullptr;
-  }
   if (state->getgrent_idx < 0) {
     return nullptr;
   }
@@ -729,7 +676,6 @@
   size_t start = 0;
   ssize_t end = android_id_count;
   if (state->getgrent_idx < end) {
-    init_group_state(state);
     return android_iinfo_to_group(state, android_ids + state->getgrent_idx++);
   }
 
@@ -737,7 +683,6 @@
   end += AID_OEM_RESERVED_END - AID_OEM_RESERVED_START + 1;
 
   if (state->getgrent_idx < end) {
-    init_group_state(state);
     return oem_id_to_group(
         state->getgrent_idx++ - start + AID_OEM_RESERVED_START, state);
   }
@@ -746,7 +691,6 @@
   end += AID_OEM_RESERVED_2_END - AID_OEM_RESERVED_2_START + 1;
 
   if (state->getgrent_idx < end) {
-    init_group_state(state);
     return oem_id_to_group(
         state->getgrent_idx++ - start + AID_OEM_RESERVED_2_START, state);
   }
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index b46839b..ebc357c 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -217,6 +217,89 @@
 TEST(pwd, getpwnam_app_id_u1_i0) {
   check_get_passwd("u1_i0", 190000, TYPE_APP);
 }
+
+TEST(pwd, getpwnam_r_alignment) {
+#if defined(__BIONIC__)
+  passwd pwd_storage;
+  alignas(16) char buf[512];
+  passwd* pwd;
+  int result = getpwnam_r("root", &pwd_storage, buf + 1, sizeof(buf) - 1, &pwd);
+  ASSERT_EQ(0, result);
+  check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwuid_r_alignment) {
+#if defined(__BIONIC__)
+  passwd pwd_storage;
+  alignas(16) char buf[512];
+  passwd* pwd;
+  int result = getpwuid_r(0, &pwd_storage, buf + 1, sizeof(buf) - 1, &pwd);
+  ASSERT_EQ(0, result);
+  check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwnam_r_reentrancy) {
+#if defined(__BIONIC__)
+  passwd pwd_storage[2];
+  char buf[2][512];
+  passwd* pwd[3];
+  int result = getpwnam_r("root", &pwd_storage[0], buf[0], sizeof(buf[0]), &pwd[0]);
+  ASSERT_EQ(0, result);
+  check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+  pwd[1] = getpwnam("system");
+  ASSERT_NE(nullptr, pwd[1]);
+  check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+  result = getpwnam_r("radio", &pwd_storage[1], buf[1], sizeof(buf[1]), &pwd[2]);
+  ASSERT_EQ(0, result);
+  check_passwd(pwd[2], "radio", 1001, TYPE_SYSTEM, true);
+  check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+  check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwuid_r_reentrancy) {
+#if defined(__BIONIC__)
+  passwd pwd_storage[2];
+  char buf[2][512];
+  passwd* pwd[3];
+  int result = getpwuid_r(0, &pwd_storage[0], buf[0], sizeof(buf[0]), &pwd[0]);
+  ASSERT_EQ(0, result);
+  check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+  pwd[1] = getpwuid(1000);
+  ASSERT_NE(nullptr, pwd[1]);
+  check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+  result = getpwuid_r(1001, &pwd_storage[1], buf[1], sizeof(buf[1]), &pwd[2]);
+  ASSERT_EQ(0, result);
+  check_passwd(pwd[2], "radio", 1001, TYPE_SYSTEM, true);
+  check_passwd(pwd[0], "root", 0, TYPE_SYSTEM, true);
+  check_passwd(pwd[1], "system", 1000, TYPE_SYSTEM, true);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(pwd, getpwnam_r_large_enough_suggested_buffer_size) {
+#if defined(__BIONIC__)
+  long size = sysconf(_SC_GETPW_R_SIZE_MAX);
+  ASSERT_GT(size, 0);
+  char buf[size];
+  passwd pwd_storage;
+  passwd* pwd;
+  ASSERT_EQ(0, getpwnam_r("root", &pwd_storage, buf, size, &pwd));
+  check_passwd(pwd, "root", 0, TYPE_SYSTEM, true);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
 #if defined(__BIONIC__)
 template <typename T>
 static void expect_ids(const T& ids) {
@@ -477,6 +560,32 @@
   check_get_group("u1_i0", 190000);
 }
 
+TEST(grp, getgrnam_r_alignment) {
+#if defined(__BIONIC__)
+  group grp_storage;
+  alignas(16) char buf[512];
+  group* grp;
+  int result = getgrnam_r("root", &grp_storage, buf + 1, sizeof(buf) - 1, &grp);
+  ASSERT_EQ(0, result);
+  check_group(grp, "root", 0);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+TEST(grp, getgrgid_r_alignment) {
+#if defined(__BIONIC__)
+  group grp_storage;
+  alignas(16) char buf[512];
+  group* grp;
+  int result = getgrgid_r(0, &grp_storage, buf + 1, sizeof(buf) - 1, &grp);
+  ASSERT_EQ(0, result);
+  check_group(grp, "root", 0);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
 TEST(grp, getgrnam_r_reentrancy) {
 #if defined(__BIONIC__)
   group grp_storage[2];
diff --git a/tests/leak_test.cpp b/tests/leak_test.cpp
index 1fa9e56..6005209 100644
--- a/tests/leak_test.cpp
+++ b/tests/leak_test.cpp
@@ -124,17 +124,22 @@
 // http://b/36045112
 TEST(pthread_leak, detach) {
   LeakChecker lc;
+  constexpr int kThreadCount = 100;
 
-  for (size_t pass = 0; pass < 2; ++pass) {
-    constexpr int kThreadCount = 100;
+  // Devices with low power cores/low number of cores can not finish test in time hence decreasing
+  // threads count to 90.
+  // http://b/129924384.
+  int threads_count = (sysconf(_SC_NPROCESSORS_CONF) > 2) ? kThreadCount : (kThreadCount - 10);
+
+  for (size_t pass = 0; pass < 1; ++pass) {
     struct thread_data { pthread_barrier_t* barrier; pid_t* tid; } threads[kThreadCount] = {};
 
     pthread_barrier_t barrier;
-    ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, kThreadCount + 1), 0);
+    ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, threads_count + 1), 0);
 
     // Start child threads.
     pid_t tids[kThreadCount];
-    for (int i = 0; i < kThreadCount; ++i) {
+    for (int i = 0; i < threads_count; ++i) {
       threads[i] = {&barrier, &tids[i]};
       const auto thread_function = +[](void* ptr) -> void* {
         thread_data* data = static_cast<thread_data*>(ptr);
diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
index 0ff6f30..e620ecd 100644
--- a/tests/stack_unwinding_test.cpp
+++ b/tests/stack_unwinding_test.cpp
@@ -112,6 +112,10 @@
 }
 
 TEST(stack_unwinding, unwind_through_signal_frame) {
+#if defined(__i386__)
+  GTEST_SKIP() << "Temporarily skip test since it fails on x86 see b/132763120.";
+#endif
+
   ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler);
 
   UnwindTest();
@@ -119,6 +123,10 @@
 
 // On LP32, the SA_SIGINFO flag gets you __restore_rt instead of __restore.
 TEST(stack_unwinding, unwind_through_signal_frame_SA_SIGINFO) {
+#if defined(__i386__)
+  GTEST_SKIP() << "Temporarily skip test since it fails on x86 see b/132763120.";
+#endif
+
   ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler, SA_SIGINFO);
 
   UnwindTest();