Merge "Remove the useless indirection in mips' __set_tls."
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 2c2b74b..41ecd09 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -89,9 +89,11 @@
   // 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 is non-POSIX and unused (always NULL) in bionic.
-  // pw_gecos is non-POSIX and missing in bionic.
+  // pw_passwd and pw_gecos are non-POSIX and unused (always NULL) in bionic.
   dst->pw_passwd = NULL;
+#ifdef __LP64__
+  dst->pw_gecos = NULL;
+#endif
 
   // Copy the integral fields.
   dst->pw_gid = src->pw_gid;
diff --git a/libc/include/pwd.h b/libc/include/pwd.h
index 6f3fad5..6d483c0 100644
--- a/libc/include/pwd.h
+++ b/libc/include/pwd.h
@@ -100,12 +100,15 @@
 
 struct passwd
 {
-    char* pw_name;
-    char* pw_passwd;
-    uid_t pw_uid;
-    gid_t pw_gid;
-    char* pw_dir;
-    char* pw_shell;
+  char* pw_name;
+  char* pw_passwd;
+  uid_t pw_uid;
+  gid_t pw_gid;
+#ifdef __LP64__
+  char* pw_gecos;
+#endif
+  char* pw_dir;
+  char* pw_shell;
 };
 
 __BEGIN_DECLS
diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h
index 3d8179e..3495546 100644
--- a/libc/include/sys/statvfs.h
+++ b/libc/include/sys/statvfs.h
@@ -23,6 +23,12 @@
 
 __BEGIN_DECLS
 
+#ifdef __LP64__
+#define __STATVFS64_RESERVED uint32_t __f_reserved[6];
+#else
+#define __STATVFS64_RESERVED
+#endif
+
 #define __STATVFS64_BODY \
   unsigned long f_bsize; \
   unsigned long f_frsize; \
@@ -35,10 +41,14 @@
   unsigned long f_fsid; \
   unsigned long f_flag; \
   unsigned long f_namemax; \
+  __STATVFS64_RESERVED
 
 struct statvfs { __STATVFS64_BODY };
 struct statvfs64 { __STATVFS64_BODY };
 
+#undef __STATVFS64_BODY
+#undef __STATVFS64_RESERVED
+
 #define ST_RDONLY      0x0001
 #define ST_NOSUID      0x0002
 #define ST_NODEV       0x0004
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 1f32f6d..b61e041 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -59,7 +59,6 @@
  *
  * open issues / todo:
  *
- * - are we doing everything we should for ARM_COPY relocations?
  * - cleaner error reporting
  * - after linking, set as much stuff as possible to READONLY
  *   and NOEXEC
@@ -1024,52 +1023,17 @@
         break;
 
     case R_AARCH64_COPY:
-        if ((si->flags & FLAG_EXE) == 0) {
-            /*
-              * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
-              *
-              * Section 4.7.1.10 "Dynamic relocations"
-              * R_AARCH64_COPY may only appear in executable objects where e_type is
-              * set to ET_EXEC.
-              *
-              * FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
-              * We should explicitly disallow ET_DYN executables from having
-              * R_AARCH64_COPY relocations.
-              */
-            DL_ERR("%s R_AARCH64_COPY relocations only supported for ET_EXEC", si->name);
-            return -1;
-        }
-        count_relocation(kRelocCopy);
-        MARK(rela->r_offset);
-        TRACE_TYPE(RELO, "RELO COPY %16llx <- %lld @ %16llx %s\n",
-                   reloc,
-                   s->st_size,
-                   (sym_addr + rela->r_addend),
-                   sym_name);
-        if (reloc == (sym_addr + rela->r_addend)) {
-            ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
-
-            if (src == NULL) {
-                DL_ERR("%s R_AARCH64_COPY relocation source cannot be resolved", si->name);
-                return -1;
-            }
-            if (lsi->has_DT_SYMBOLIC) {
-                DL_ERR("%s invalid R_AARCH64_COPY relocation against DT_SYMBOLIC shared "
-                       "library %s (built with -Bsymbolic?)", si->name, lsi->name);
-                return -1;
-            }
-            if (s->st_size < src->st_size) {
-                DL_ERR("%s R_AARCH64_COPY relocation size mismatch (%lld < %lld)",
-                       si->name, s->st_size, src->st_size);
-                return -1;
-            }
-            memcpy(reinterpret_cast<void*>(reloc),
-                   reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
-        } else {
-            DL_ERR("%s R_AARCH64_COPY relocation target cannot be resolved", si->name);
-            return -1;
-        }
-        break;
+        /*
+         * ET_EXEC is not supported so this should not happen.
+         *
+         * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+         *
+         * Section 4.7.1.10 "Dynamic relocations"
+         * R_AARCH64_COPY may only appear in executable objects where e_type is
+         * set to ET_EXEC.
+         */
+        DL_ERR("%s R_AARCH64_COPY relocations are not supported", si->name);
+        return -1;
     case R_AARCH64_TLS_TPREL64:
         TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
                    reloc, (sym_addr + rela->r_addend), rela->r_offset);
@@ -1247,48 +1211,17 @@
             *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
             break;
         case R_ARM_COPY:
-            if ((si->flags & FLAG_EXE) == 0) {
-                /*
-                 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
-                 *
-                 * Section 4.7.1.10 "Dynamic relocations"
-                 * R_ARM_COPY may only appear in executable objects where e_type is
-                 * set to ET_EXEC.
-                 *
-                 * TODO: FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
-                 * We should explicitly disallow ET_DYN executables from having
-                 * R_ARM_COPY relocations.
-                 */
-                DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", si->name);
-                return -1;
-            }
-            count_relocation(kRelocCopy);
-            MARK(rel->r_offset);
-            TRACE_TYPE(RELO, "RELO %08x <- %d @ %08x %s", reloc, s->st_size, sym_addr, sym_name);
-            if (reloc == sym_addr) {
-                ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
-
-                if (src == NULL) {
-                    DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", si->name);
-                    return -1;
-                }
-                if (lsi->has_DT_SYMBOLIC) {
-                    DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
-                           "library %s (built with -Bsymbolic?)", si->name, lsi->name);
-                    return -1;
-                }
-                if (s->st_size < src->st_size) {
-                    DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
-                           si->name, s->st_size, src->st_size);
-                    return -1;
-                }
-                memcpy(reinterpret_cast<void*>(reloc),
-                       reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
-            } else {
-                DL_ERR("%s R_ARM_COPY relocation target cannot be resolved", si->name);
-                return -1;
-            }
-            break;
+            /*
+             * ET_EXEC is not supported so this should not happen.
+             *
+             * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+             *
+             * Section 4.7.1.10 "Dynamic relocations"
+             * R_ARM_COPY may only appear in executable objects where e_type is
+             * set to ET_EXEC.
+             */
+            DL_ERR("%s R_ARM_COPY relocations are not supported", si->name);
+            return -1;
 #elif defined(__i386__)
         case R_386_JMP_SLOT:
             count_relocation(kRelocAbsolute);
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 73e9dcd..8f6ee2b 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -102,14 +102,12 @@
   ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1);
   ASSERT_EQ(EINVAL, errno);
 
-  // The stream can't be closed.
-  fclose(fp);
+  // The underlying fd can't be closed.
+  ASSERT_EQ(0, close(fileno(fp)));
   errno = 0;
   ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1);
-  // glibc sometimes doesn't set errno in this particular case.
-#if defined(__BIONIC__)
   ASSERT_EQ(EBADF, errno);
-#endif // __BIONIC__
+  fclose(fp);
 }
 
 TEST(stdio, getline) {
@@ -171,14 +169,12 @@
   ASSERT_EQ(getline(&buffer, NULL, fp), -1);
   ASSERT_EQ(EINVAL, errno);
 
-  // The stream can't be closed.
-  fclose(fp);
+  // The underlying fd can't be closed.
+  ASSERT_EQ(0, close(fileno(fp)));
   errno = 0;
   ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1);
-  // glibc sometimes doesn't set errno in this particular case.
-#if defined(__BIONIC__)
   ASSERT_EQ(EBADF, errno);
-#endif // __BIONIC__
+  fclose(fp);
 }
 
 TEST(stdio, printf_ssize_t) {
diff --git a/tests/stubs_test.cpp b/tests/stubs_test.cpp
index 7d70aa6..9b0c231 100644
--- a/tests/stubs_test.cpp
+++ b/tests/stubs_test.cpp
@@ -41,6 +41,10 @@
   EXPECT_STREQ(username, pwd->pw_name);
   EXPECT_EQ(uid, pwd->pw_uid);
   EXPECT_EQ(uid, pwd->pw_gid);
+  ASSERT_EQ(NULL, pwd->pw_passwd);
+#ifdef __LP64__
+  ASSERT_EQ(NULL, pwd->pw_gecos);
+#endif
 
   if (uid_type == TYPE_SYSTEM) {
     EXPECT_STREQ("/", pwd->pw_dir);