Merge "Add comments about the -shared flag."
diff --git a/libc/Android.mk b/libc/Android.mk
index 2f534c3..71ddbd3 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -944,6 +944,26 @@
 include $(BUILD_STATIC_LIBRARY)
 
 # ========================================================
+# libc_ndk.a
+# Compatibility library for the NDK. This library contains
+# all the parts of libc that are safe to statically link.
+# We can't safely statically link things that can only run
+# on a certain version of the OS. Examples include
+# anything that talks to netd (a large portion of the DNS
+# code) and anything that is dependent on the layout of a
+# data structure that has changed across releases (such as
+# pthread_t).
+# ========================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libc_ndk
+LOCAL_WHOLE_STATIC_LIBRARIES := libc_syscalls libm
+LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
+
+include $(BUILD_STATIC_LIBRARY)
+
+# ========================================================
 # libc_common.a
 # ========================================================
 
diff --git a/libc/tools/ndk_missing_symbols.py b/libc/tools/ndk_missing_symbols.py
index 7b22ca8..a9f92b1 100755
--- a/libc/tools/ndk_missing_symbols.py
+++ b/libc/tools/ndk_missing_symbols.py
@@ -33,10 +33,14 @@
     adb_pull('/system/lib/libm.so', tmp_dir)
 
     current = symbols.GetFromAndroidSo(['libc.so', 'libm.so'])
-    device = (symbols.GetFromSo(os.path.join(tmp_dir, 'libc.so')) |
-              symbols.GetFromSo(os.path.join(tmp_dir, 'libm.so')))
+    device = (symbols.GetFromElf(os.path.join(tmp_dir, 'libc.so')) |
+              symbols.GetFromElf(os.path.join(tmp_dir, 'libm.so')))
+    compat_lib = symbols.GetFromAndroidStaticLib(['libc_ndk.a'])
 
-    for symbol in sorted(current - device):
+    missing_symbols = current - device
+    compat_not_covered = missing_symbols - compat_lib
+
+    for symbol in sorted(compat_not_covered):
         print symbol
 
 
diff --git a/libc/tools/symbols.py b/libc/tools/symbols.py
index 43454e4..3f40aad 100644
--- a/libc/tools/symbols.py
+++ b/libc/tools/symbols.py
@@ -28,7 +28,7 @@
     return symbols
 
 
-def GetFromSo(so_file):
+def GetFromElf(elf_file, sym_type='--dyn-syms'):
     # pylint: disable=line-too-long
     # Example readelf output:
     #     264: 0001623c         4 FUNC        GLOBAL DEFAULT        8 cabsf
@@ -41,7 +41,7 @@
 
     symbols = set()
 
-    output = subprocess.check_output(['readelf', '--dyn-syms', '-W', so_file])
+    output = subprocess.check_output(['readelf', sym_type, '-W', elf_file])
     for line in output.split('\n'):
         if ' HIDDEN ' in line or ' UND ' in line:
             continue
@@ -54,6 +54,22 @@
     return symbols
 
 
+def GetFromAndroidStaticLib(files):
+    out_dir = os.environ['ANDROID_PRODUCT_OUT']
+    lib_dir = os.path.join(out_dir, 'obj')
+
+    results = set()
+    for f in files:
+        static_lib_dir = os.path.join(
+            lib_dir,
+            'STATIC_LIBRARIES',
+            '{}_intermediates'.format(os.path.splitext(f)[0]))
+        results |= GetFromElf(
+            os.path.join(static_lib_dir, f),
+            sym_type='--syms')
+    return results
+
+
 def GetFromAndroidSo(files):
     out_dir = os.environ['ANDROID_PRODUCT_OUT']
     lib_dir = os.path.join(out_dir, 'system/lib64')
@@ -62,7 +78,7 @@
 
     results = set()
     for f in files:
-        results |= GetFromSo(os.path.join(lib_dir, f))
+        results |= GetFromElf(os.path.join(lib_dir, f))
     return results
 
 
@@ -70,5 +86,5 @@
     lib_dir = '/lib/x86_64-linux-gnu'
     results = set()
     for f in files:
-        results |= GetFromSo(glob.glob(os.path.join(lib_dir, f))[-1])
+        results |= GetFromElf(glob.glob(os.path.join(lib_dir, f))[-1])
     return results
diff --git a/linker/Android.mk b/linker/Android.mk
index 989b0d2..54535fc 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -38,6 +38,7 @@
 
 LOCAL_CPPFLAGS += \
     -std=gnu++11 \
+    -Wold-style-cast \
 
 ifeq ($(TARGET_IS_64_BIT),true)
 LOCAL_CPPFLAGS += -DTARGET_IS_64_BIT
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index decc22c..c889544 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -151,7 +151,7 @@
   }
 
   char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination
-  if (prctl(PR_GET_NAME, (unsigned long)thread_name, 0, 0, 0) != 0) {
+  if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name), 0, 0, 0) != 0) {
     strcpy(thread_name, "<name unknown>");
   } else {
     // short names are null terminated by prctl, but the man page
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 0b0afc3..df8e52e 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -71,6 +71,10 @@
  *   and NOEXEC
  */
 
+// Override macros to use C++ style casts
+#undef ELF_ST_TYPE
+#define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
+
 #if defined(__LP64__)
 #define SEARCH_NAME(x) x
 #else
@@ -364,12 +368,12 @@
 //
 // This function is exposed via dlfcn.cpp and libdl.so.
 _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
-  unsigned addr = (unsigned)pc;
+  uintptr_t addr = reinterpret_cast<uintptr_t>(pc);
 
   for (soinfo* si = solist; si != 0; si = si->next) {
     if ((addr >= si->base) && (addr < (si->base + si->size))) {
         *pcount = si->ARM_exidx_count;
-        return (_Unwind_Ptr)si->ARM_exidx;
+        return reinterpret_cast<_Unwind_Ptr>(si->ARM_exidx);
     }
   }
   *pcount = 0;
@@ -2090,7 +2094,7 @@
         break;
 
       case DT_INIT_ARRAYSZ:
-        init_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
+        init_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
         break;
 
       case DT_FINI_ARRAY:
@@ -2099,7 +2103,7 @@
         break;
 
       case DT_FINI_ARRAYSZ:
-        fini_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
+        fini_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
         break;
 
       case DT_PREINIT_ARRAY:
@@ -2108,7 +2112,7 @@
         break;
 
       case DT_PREINIT_ARRAYSZ:
-        preinit_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
+        preinit_array_count_ = static_cast<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
         break;
 
       case DT_TEXTREL:
@@ -2671,6 +2675,8 @@
 
   protect_data(PROT_READ);
 
+  INFO("[ jumping to _start ]");
+
   // Return the address that the calling assembly stub should jump to.
   return start_address;
 }
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index ffd4de2..af4dc25 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -688,7 +688,7 @@
  */
 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                              ElfW(Addr) load_bias,
-                             ElfW(Addr)** arm_exidx, unsigned* arm_exidx_count) {
+                             ElfW(Addr)** arm_exidx, size_t* arm_exidx_count) {
   const ElfW(Phdr)* phdr = phdr_table;
   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
 
@@ -698,7 +698,7 @@
     }
 
     *arm_exidx = reinterpret_cast<ElfW(Addr)*>(load_bias + phdr->p_vaddr);
-    *arm_exidx_count = (unsigned)(phdr->p_memsz / 8);
+    *arm_exidx_count = phdr->p_memsz / 8;
     return 0;
   }
   *arm_exidx = nullptr;
@@ -757,7 +757,7 @@
         ElfW(Addr)  elf_addr = load_bias_ + phdr->p_vaddr;
         const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(elf_addr);
         ElfW(Addr)  offset = ehdr->e_phoff;
-        return CheckPhdr((ElfW(Addr))ehdr + offset);
+        return CheckPhdr(reinterpret_cast<ElfW(Addr)>(ehdr) + offset);
       }
       break;
     }
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 65d302c..6b917b4 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -98,7 +98,7 @@
 
 #if defined(__arm__)
 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias,
-                             ElfW(Addr)** arm_exidx, unsigned* arm_exidix_count);
+                             ElfW(Addr)** arm_exidx, size_t* arm_exidix_count);
 #endif
 
 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count,
diff --git a/tests/Android.mk b/tests/Android.mk
index 3150655..11fb2c8 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -369,7 +369,7 @@
 
 LOCAL_CLANG := false
 LOCAL_MODULE := bionic-compile-time-tests-g++
-LOCAL_CXXFLAGS := -Wall
+LOCAL_CPPFLAGS := -Wall
 LOCAL_SRC_FILES := fortify_sprintf_warnings.cpp
 include $(BUILD_STATIC_LIBRARY)
 
@@ -386,7 +386,7 @@
 
 LOCAL_CLANG := true
 LOCAL_MODULE := bionic-compile-time-tests-clang++
-LOCAL_CXXFLAGS := -Wall
+LOCAL_CPPFLAGS := -Wall
 # FileCheck will error if there aren't any CLANG: lines in the file, but there
 # don't appear to be any cases where clang _does_ emit warnings for sn?printf :(
 LOCAL_SRC_FILES :=
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 6d7e72b..0e24325 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -107,7 +107,7 @@
     ASSERT_FALSE(feof(fp));
     ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i])));
     ASSERT_GE(allocated_length, strlen(expected[i]));
-    ASSERT_STREQ(word_read, expected[i]);
+    ASSERT_STREQ(expected[i], word_read);
   }
   // The last read should have set the end-of-file indicator for the stream.
   ASSERT_TRUE(feof(fp));
@@ -171,7 +171,7 @@
   while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) {
     ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written)));
     ASSERT_GE(allocated_length, strlen(line_written));
-    ASSERT_STREQ(line_read, line_written);
+    ASSERT_STREQ(line_written, line_read);
     ++read_line_count;
   }
   ASSERT_EQ(read_line_count, line_count);
@@ -889,23 +889,24 @@
   }
 }
 
-TEST(fread, fread_EOF) {
-  const char* digits = "0123456789";
-  FILE* fp = fmemopen((char*) digits, sizeof(digits), "r");
+TEST(stdio, fread_EOF) {
+  std::string digits("0123456789");
+  FILE* fp = fmemopen(&digits[0], digits.size(), "r");
 
   // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
   char buf1[4 * 4];
   memset(buf1, 0, sizeof(buf1));
   ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
-  ASSERT_STREQ(buf1, "01234567");
+  ASSERT_STREQ("0123456789", buf1);
   ASSERT_TRUE(feof(fp));
 
   rewind(fp);
 
-  char buf2[4 * 4];
+  // Try to read way too much so stdio tries to read more direct from the stream.
+  char buf2[4 * 4096];
   memset(buf2, 0, sizeof(buf2));
   ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
-  ASSERT_STREQ(buf2, "01234567");
+  ASSERT_STREQ("0123456789", buf2);
   ASSERT_TRUE(feof(fp));
 
   fclose(fp);