Merge changes from topic "cfi-shadow-size"

* changes:
  Revert "Revert "arm64: expand CFI shadow to cover 48-bit virtual addresses""
  [cfi] Export __cfi_shadow_size.
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index 0edba65..93f62cf 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -25,6 +25,7 @@
         "-Wunused",
     ],
     srcs: [
+        "bionic_benchmarks.cpp",
         "atomic_benchmark.cpp",
         "math_benchmark.cpp",
         "property_benchmark.cpp",
@@ -34,8 +35,13 @@
         "string_benchmark.cpp",
         "time_benchmark.cpp",
         "unistd_benchmark.cpp",
+        "stdlib_benchmark.cpp",
     ],
-    static_libs: ["libBionicBenchmarksUtils"],
+    shared_libs: ["libtinyxml2"],
+    static_libs: [
+        "libbase",
+        "libBionicBenchmarksUtils",
+    ],
 }
 
 cc_defaults {
@@ -54,6 +60,7 @@
 cc_benchmark {
     name: "bionic-benchmarks",
     defaults: ["bionic-benchmarks-defaults"],
+    data: ["suites/*"],
 }
 
 // We don't build a static benchmark executable because it's not usually
@@ -87,6 +94,8 @@
     defaults: ["bionic-benchmarks-extras-defaults"],
     srcs: [
         "tests/benchmark_test.cpp",
+        "tests/interface_test.cpp",
     ],
     static_libs: ["libBionicBenchmarksUtils"],
+    data: ["suites/test_*.xml"],
 }
diff --git a/benchmarks/atomic_benchmark.cpp b/benchmarks/atomic_benchmark.cpp
index 66a0120..a584dce 100644
--- a/benchmarks/atomic_benchmark.cpp
+++ b/benchmarks/atomic_benchmark.cpp
@@ -20,10 +20,12 @@
 // Expected mappings from C++ atomics to hardware primitives can be found at
 // http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html .
 
-#include <benchmark/benchmark.h>
 #include <atomic>
 #include <mutex>
 
+#include <benchmark/benchmark.h>
+#include "util.h"
+
 // We time atomic operations separated by a volatile (not atomic!) increment.  This ensures
 // that the compiler emits memory instructions (e.g. load or store) prior to any fence or the
 // like.  That in turn ensures that the CPU has outstanding memory operations when the fence
@@ -48,7 +50,7 @@
     ++counter;
   }
 }
-BENCHMARK(BM_empty);
+BIONIC_BENCHMARK(BM_empty);
 
 static void BM_load_relaxed(benchmark::State& state) {
   unsigned result = 0;
@@ -58,7 +60,7 @@
   }
   sink = result;
 }
-BENCHMARK(BM_load_relaxed);
+BIONIC_BENCHMARK(BM_load_relaxed);
 
 static void BM_load_acquire(benchmark::State& state) {
   unsigned result = 0;
@@ -68,7 +70,7 @@
   }
   sink = result;
 }
-BENCHMARK(BM_load_acquire);
+BIONIC_BENCHMARK(BM_load_acquire);
 
 static void BM_store_release(benchmark::State& state) {
   int i = counter;
@@ -77,7 +79,7 @@
     ++counter;
   }
 }
-BENCHMARK(BM_store_release);
+BIONIC_BENCHMARK(BM_store_release);
 
 static void BM_store_seq_cst(benchmark::State& state) {
   int i = counter;
@@ -86,7 +88,7 @@
     ++counter;
   }
 }
-BENCHMARK(BM_store_seq_cst);
+BIONIC_BENCHMARK(BM_store_seq_cst);
 
 static void BM_fetch_add_relaxed(benchmark::State& state) {
   unsigned result = 0;
@@ -96,7 +98,7 @@
   }
   sink = result;
 }
-BENCHMARK(BM_fetch_add_relaxed);
+BIONIC_BENCHMARK(BM_fetch_add_relaxed);
 
 static void BM_fetch_add_seq_cst(benchmark::State& state) {
   unsigned result = 0;
@@ -106,7 +108,7 @@
   }
   sink = result;
 }
-BENCHMARK(BM_fetch_add_seq_cst);
+BIONIC_BENCHMARK(BM_fetch_add_seq_cst);
 
 // The fence benchmarks include a relaxed load to make it much harder to optimize away
 // the fence.
@@ -120,7 +122,7 @@
   }
   sink = result;
 }
-BENCHMARK(BM_acquire_fence);
+BIONIC_BENCHMARK(BM_acquire_fence);
 
 static void BM_seq_cst_fence(benchmark::State& state) {
   unsigned result = 0;
@@ -131,7 +133,7 @@
   }
   sink = result;
 }
-BENCHMARK(BM_seq_cst_fence);
+BIONIC_BENCHMARK(BM_seq_cst_fence);
 
 // For comparison, also throw in a critical section version:
 
@@ -145,4 +147,4 @@
   }
   sink = result;
 }
-BENCHMARK(BM_fetch_add_cs);
+BIONIC_BENCHMARK(BM_fetch_add_cs);
diff --git a/benchmarks/bionic_benchmarks.cpp b/benchmarks/bionic_benchmarks.cpp
new file mode 100644
index 0000000..e5a23ad
--- /dev/null
+++ b/benchmarks/bionic_benchmarks.cpp
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <err.h>
+#include <getopt.h>
+#include <math.h>
+#include <sys/resource.h>
+
+#include <map>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "android-base/strings.h"
+#include <benchmark/benchmark.h>
+#include <tinyxml2.h>
+#include "util.h"
+
+std::map<std::string, benchmark_func_t> g_str_to_func;
+
+std::mutex g_map_lock;
+
+static struct option g_long_options[] =
+{
+  {"bionic_cpu", required_argument, 0, 'c'},
+  {"bionic_xml", required_argument, 0, 'x'},
+  {"bionic_iterations", required_argument, 0, 'i'},
+  {"bionic_extra", required_argument, 0, 'a'},
+  {"help", no_argument, 0, 'h'},
+  {0, 0, 0, 0},
+};
+
+typedef std::vector<std::vector<int>> args_vector_t;
+
+void Usage() {
+  printf("Usage:\n");
+  printf("bionic_benchmarks [--bionic_cpu=<cpu_to_isolate>] [--bionic_xml=<path_to_xml>]\n");
+  printf("                  [--bionic_iterations=<num_iter>]\n");
+  printf("                  [--bionic_extra=\"<fn_name> <arg1> <arg 2> ... ]\n");
+  printf("                  [<Google benchmark flags>]\n");
+  printf("Google benchmark flags:\n");
+
+  int fake_argc = 2;
+  char argv0[] = "bionic_benchmarks";
+  char argv1[] = "--help";
+  char* fake_argv[3] {argv0, argv1, NULL};
+  benchmark::Initialize(&fake_argc, fake_argv);
+  exit(1);
+}
+
+// This function removes any bionic benchmarks command line arguments by checking them
+// against g_long_options. It fills new_argv with the filtered args.
+void SanitizeOpts(int argc, char** argv, std::vector<char*>* new_argv) {
+  // TO THOSE ADDING OPTIONS: This currently doesn't support optional arguments.
+  (*new_argv)[0] = argv[0];
+  for (int i = 1; i < argc; ++i) {
+    char* optarg = argv[i];
+    size_t opt_idx = 0;
+
+    // Iterate through g_long_options until either we hit the end or we have a match.
+    for (opt_idx = 0; g_long_options[opt_idx].name &&
+                      strncmp(g_long_options[opt_idx].name, optarg + 2,
+                              strlen(g_long_options[opt_idx].name)); ++opt_idx) {
+    }
+
+    if (!g_long_options[opt_idx].name) {
+      new_argv->push_back(optarg);
+    } else {
+      if (g_long_options[opt_idx].has_arg == required_argument) {
+        // If the arg was passed in with an =, it spans one char *.
+        // Otherwise, we skip a spot for the argument.
+        if (!strchr(optarg, '=')) {
+          i++;
+        }
+      }
+    }
+  }
+  new_argv->push_back(0);
+}
+
+bench_opts_t ParseOpts(int argc, char** argv) {
+  bench_opts_t opts;
+  int opt;
+  int option_index = 0;
+
+  opts.cpu_to_lock = LONG_MAX;
+  opts.num_iterations = 0;
+
+  // To make this parser handle the benchmark options silently:
+  extern int opterr;
+  opterr = 0;
+
+  while ((opt = getopt_long(argc, argv, "c:x:i:a:h", g_long_options, &option_index)) != -1) {
+    if (opt == -1) {
+      break;
+    }
+    switch (opt) {
+      case 'c':
+        if (*optarg) {
+          char* check_null;
+          opts.cpu_to_lock = strtol(optarg, &check_null, 10);
+          if (*check_null) {
+            errx(1, "ERROR: Args %s is not a valid integer.", optarg);
+          }
+        } else {
+          printf("ERROR: no argument specified for bionic_cpu\n");
+          Usage();
+        }
+        break;
+      case 'x':
+        if (*optarg) {
+          opts.xmlpath = optarg;
+        } else {
+          printf("ERROR: no argument specified for bionic_xml\n");
+          Usage();
+        }
+        break;
+      case 'a':
+        if (*optarg) {
+          opts.extra_benchmarks.push_back(optarg);
+        } else {
+          printf("ERROR: no argument specified for bionic_extra\n");
+          Usage();
+        }
+        break;
+      case 'i':
+        if (*optarg){
+          char* check_null;
+          opts.num_iterations = strtol(optarg, &check_null, 10);
+          if (*check_null != '\0' or opts.num_iterations < 0) {
+            errx(1, "ERROR: Args %s is not a valid number of iterations.", optarg);
+          }
+        } else {
+          printf("ERROR: no argument specified for bionic_iterations\n");
+          Usage();
+        }
+        break;
+      case 'h':
+        Usage();
+        break;
+      case '?':
+        break;
+      default:
+        exit(1);
+    }
+  }
+  return opts;
+}
+
+// This is a wrapper for every function call for per-benchmark cpu pinning.
+void LockAndRun(benchmark::State& state, benchmark_func_t func_to_bench, long cpu_to_lock) {
+  if (cpu_to_lock != LONG_MAX) LockToCPU(cpu_to_lock);
+  // To avoid having to link against Google benchmarks in libutil,
+  // benchmarks are kept without parameter information, necessitating this cast.
+  reinterpret_cast<void(*) (benchmark::State&)>(func_to_bench)(state);
+}
+
+args_vector_t* ResolveArgs(args_vector_t* to_populate, std::string args,
+                           std::map<std::string, args_vector_t>& args_shorthand) {
+  // args is either a space-separated list of ints or a macro name.
+  // To ease formatting in XML files, args is left and right trimmed.
+  if (args_shorthand.count(args)) {
+    return &args_shorthand[args];
+  }
+  to_populate->push_back(std::vector<int>());
+  std::stringstream sstream(args);
+  std::string argstr;
+  while (sstream >> argstr) {
+    char* check_null;
+    int converted = static_cast<int>(strtol(argstr.c_str(), &check_null, 10));
+    if (*check_null) {
+      errx(1, "ERROR: Args str %s contains an invalid macro or int.", args.c_str());
+    }
+    (*to_populate)[0].push_back(converted);
+  }
+  return to_populate;
+}
+
+void RegisterGoogleBenchmarks(bench_opts_t primary_opts, bench_opts_t secondary_opts,
+                         std::string fn_name, args_vector_t* run_args) {
+  if (g_str_to_func.find(fn_name) == g_str_to_func.end()) {
+    errx(1, "ERROR: No benchmark for function %s", fn_name.c_str());
+  }
+  long iterations_to_use = primary_opts.num_iterations ? primary_opts.num_iterations :
+                                                         secondary_opts.num_iterations;
+  int cpu_to_use = INT_MAX;
+  if (primary_opts.cpu_to_lock != INT_MAX) {
+    cpu_to_use = primary_opts.cpu_to_lock;
+
+  } else if (secondary_opts.cpu_to_lock != INT_MAX) {
+    cpu_to_use = secondary_opts.cpu_to_lock;
+  }
+
+  for (std::vector<int> args : (*run_args)) {
+    auto registration = benchmark::RegisterBenchmark(fn_name.c_str(), LockAndRun,
+                                                     g_str_to_func.at(fn_name),
+                                                     cpu_to_use)->Args(args);
+    if (iterations_to_use > 0) {
+      registration->Iterations(iterations_to_use);
+    }
+  }
+}
+
+void RegisterCliBenchmarks(bench_opts_t cmdline_opts,
+                           std::map<std::string, args_vector_t>& args_shorthand) {
+  // Register any of the extra benchmarks that were specified in the options.
+  args_vector_t arg_vector;
+  args_vector_t* run_args = &arg_vector;
+  for (std::string extra_fn : cmdline_opts.extra_benchmarks) {
+    android::base::Trim(extra_fn);
+    size_t first_space_pos = extra_fn.find(" ");
+    std::string fn_name = extra_fn.substr(0, first_space_pos);
+    std::string cmd_args;
+    if (first_space_pos != std::string::npos) {
+      cmd_args = extra_fn.substr(extra_fn.find(" ") + 1);
+    } else {
+      cmd_args = "";
+    }
+    run_args = ResolveArgs(run_args, cmd_args, args_shorthand);
+    RegisterGoogleBenchmarks(bench_opts_t(), cmdline_opts, fn_name, run_args);
+
+    run_args = &arg_vector;
+    arg_vector.clear();
+  }
+}
+
+int RegisterXmlBenchmarks(bench_opts_t cmdline_opts,
+                          std::map<std::string, args_vector_t>& args_shorthand) {
+  // Structure of the XML file:
+  // - Element "fn"           Function to benchmark.
+  // - - Element "iterations" Number of iterations to run. Leaving this blank uses
+  //                          Google benchmarks' convergence heuristics.
+  // - - Element "cpu"        CPU to isolate to, if any.
+  // - - Element "args"       Whitespace-separated list of per-function integer arguments, or
+  //                          one of the macros defined in util.h.
+  tinyxml2::XMLDocument doc;
+  if (doc.LoadFile(cmdline_opts.xmlpath.c_str()) != tinyxml2::XML_SUCCESS) {
+    doc.PrintError();
+    return doc.ErrorID();
+  }
+
+  // Read and register the functions.
+  tinyxml2::XMLNode* fn = doc.FirstChildElement("fn");
+  args_vector_t arg_vector;
+  args_vector_t* run_args = &arg_vector;
+  while (fn) {
+    auto fn_elem = fn->FirstChildElement("name");
+    if (!fn_elem) {
+      errx(1, "ERROR: Malformed XML entry: missing name element.");
+    }
+    std::string fn_name = fn_elem->GetText();
+    if (fn_name.empty()) {
+      errx(1, "ERROR: Malformed XML entry: error parsing name text.");
+    }
+    auto* xml_args = fn->FirstChildElement("args");
+    run_args = ResolveArgs(run_args, xml_args ? android::base::Trim(xml_args->GetText()) : "",
+                           args_shorthand);
+
+    // XML values for CPU and iterations take precedence over those passed in via CLI.
+    bench_opts_t xml_opts{};
+    auto* num_iterations_elem = fn->FirstChildElement("iterations");
+    if (num_iterations_elem) {
+      int temp;
+      num_iterations_elem->QueryIntText(&temp);
+      xml_opts.num_iterations = temp;
+    } else {
+      xml_opts.num_iterations = 0;
+    }
+    auto* cpu_to_lock_elem = fn->FirstChildElement("cpu");
+    if (cpu_to_lock_elem) {
+      int temp;
+      cpu_to_lock_elem->QueryIntText(&temp);
+      xml_opts.cpu_to_lock = temp;
+    } else {
+      xml_opts.cpu_to_lock = INT_MAX;
+    }
+
+    RegisterGoogleBenchmarks(xml_opts, cmdline_opts, fn_name, run_args);
+
+    fn = fn->NextSibling();
+    run_args = &arg_vector;
+    arg_vector.clear();
+  }
+  return 0;
+}
+
+std::map<std::string, args_vector_t> GetShorthand() {
+  std::map<std::string, args_vector_t> args_shorthand {
+    {"AT_ALIGNED_TWOBUF", args_vector_t{ {8, 0, 0},
+                                         {64, 0, 0},
+                                         {512, 0, 0},
+                                         {1 * KB, 0, 0},
+                                         {8 * KB, 0, 0},
+                                         {16 * KB, 0, 0},
+                                         {32 * KB, 0, 0},
+                                         {64 * KB, 0, 0} }},
+    {"AT_ALIGNED_ONEBUF", args_vector_t{ {(8), 0},
+                                         {(64), 0},
+                                         {(512), 0},
+                                         {(1*KB), 0},
+                                         {(8*KB), 0},
+                                         {(16*KB), 0},
+                                         {(32*KB), 0},
+                                         {(64*KB), 0}}},
+
+    {"AT_COMMON_SIZES", args_vector_t{ {8}, {64}, {512}, {1*KB}, {8*KB}, {16*KB},
+                                                       {32*KB}, {64*KB}}},
+
+    // Do not exceed 512. that is about the largest number of properties
+    // that can be created with the current property area size.
+    {"NUM_PROPS", args_vector_t{ {1}, {4}, {16}, {64}, {128}, {256}, {512} }},
+
+    {"MATH_COMMON", args_vector_t{ {0}, {1}, {2}, {3} }}
+  };
+  for (int i = 1; i < 15; i++) {
+    int align = pow(2, i);
+    std::stringstream sstream;
+    sstream << "AT_" << align << "_ALIGN_TWOBUF";
+    args_shorthand.emplace(sstream.str(),
+                           args_vector_t{ {8, align, align},
+                                          {64, align, align},
+                                          {512, align, align},
+                                          {1 * KB, align, align},
+                                          {8 * KB, align, align},
+                                          {16 * KB, align, align},
+                                          {32 * KB, align, align},
+                                          {64 * KB, align, align} });
+    sstream.str("");
+    sstream << "AT_" << align << "_ALIGN_ONEBUF";
+    args_shorthand.emplace(sstream.str(),
+                            args_vector_t{ {(8), align},
+                                           {(64), align},
+                                           {(512), align},
+                                           {(1*KB), align},
+                                           {(8*KB), align},
+                                           {(16*KB), align},
+                                           {(32*KB), align},
+                                           {(64*KB), align} });
+    sstream.str("");
+  }
+  return args_shorthand;
+}
+
+
+int main(int argc, char** argv) {
+  std::map<std::string, args_vector_t> args_shorthand = GetShorthand();
+  bench_opts_t opts = ParseOpts(argc, argv);
+  std::vector<char*> new_argv(argc);
+  SanitizeOpts(argc, argv, &new_argv);
+
+  if (!opts.xmlpath.empty()) {
+    if (int err = RegisterXmlBenchmarks(opts, args_shorthand)) {
+      return err;
+    }
+  }
+  RegisterCliBenchmarks(opts, args_shorthand);
+
+  // Set the thread priority to the maximum.
+  if (setpriority(PRIO_PROCESS, 0, -20)) {
+    perror("Failed to raise priority of process. Are you root?\n");
+  }
+
+  int new_argc = new_argv.size();
+  benchmark::Initialize(&new_argc, new_argv.data());
+  benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/benchmarks/math_benchmark.cpp b/benchmarks/math_benchmark.cpp
index a411c9c..7b9a283 100644
--- a/benchmarks/math_benchmark.cpp
+++ b/benchmarks/math_benchmark.cpp
@@ -18,11 +18,11 @@
 #include <math.h>
 
 #include <benchmark/benchmark.h>
+#include "util.h"
 
 static const double values[] = { 1234.0, nan(""), HUGE_VAL, 0.0 };
 static const char* names[] = { "1234.0", "nan", "HUGE_VAL", "0.0" };
 
-#define BENCHMARK_COMMON_VALS(name) BENCHMARK(name)->Arg(0)->Arg(1)->Arg(2)->Arg(3)
 
 static void SetLabel(benchmark::State& state) {
   state.SetLabel(names[state.range(0)]);
@@ -39,7 +39,7 @@
     d += sqrt(v);
   }
 }
-BENCHMARK(BM_math_sqrt);
+BIONIC_BENCHMARK(BM_math_sqrt);
 
 static void BM_math_log10(benchmark::State& state) {
   d = 0.0;
@@ -48,7 +48,7 @@
     d += log10(v);
   }
 }
-BENCHMARK(BM_math_log10);
+BIONIC_BENCHMARK(BM_math_log10);
 
 static void BM_math_logb(benchmark::State& state) {
   d = 0.0;
@@ -57,7 +57,7 @@
     d += logb(v);
   }
 }
-BENCHMARK(BM_math_logb);
+BIONIC_BENCHMARK(BM_math_logb);
 
 static void BM_math_isfinite_macro(benchmark::State& state) {
   d = 0.0;
@@ -67,7 +67,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isfinite_macro);
+BIONIC_BENCHMARK(BM_math_isfinite_macro);
 
 #if defined(__BIONIC__)
 #define test_isfinite __isfinite
@@ -82,7 +82,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isfinite);
+BIONIC_BENCHMARK(BM_math_isfinite);
 
 static void BM_math_isinf_macro(benchmark::State& state) {
   d = 0.0;
@@ -92,7 +92,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isinf_macro);
+BIONIC_BENCHMARK(BM_math_isinf_macro);
 
 static void BM_math_isinf(benchmark::State& state) {
   d = 0.0;
@@ -102,7 +102,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isinf);
+BIONIC_BENCHMARK(BM_math_isinf);
 
 static void BM_math_isnan_macro(benchmark::State& state) {
   d = 0.0;
@@ -112,7 +112,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isnan_macro);
+BIONIC_BENCHMARK(BM_math_isnan_macro);
 
 static void BM_math_isnan(benchmark::State& state) {
   d = 0.0;
@@ -122,7 +122,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isnan);
+BIONIC_BENCHMARK(BM_math_isnan);
 
 static void BM_math_isnormal_macro(benchmark::State& state) {
   d = 0.0;
@@ -132,7 +132,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isnormal_macro);
+BIONIC_BENCHMARK(BM_math_isnormal_macro);
 
 #if defined(__BIONIC__)
 static void BM_math_isnormal(benchmark::State& state) {
@@ -143,7 +143,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_isnormal);
+BIONIC_BENCHMARK(BM_math_isnormal);
 #endif
 
 static void BM_math_sin_fast(benchmark::State& state) {
@@ -152,7 +152,7 @@
     d += sin(d);
   }
 }
-BENCHMARK(BM_math_sin_fast);
+BIONIC_BENCHMARK(BM_math_sin_fast);
 
 static void BM_math_sin_feupdateenv(benchmark::State& state) {
   d = 1.0;
@@ -164,7 +164,7 @@
     feupdateenv(&__libc_save_rm);
   }
 }
-BENCHMARK(BM_math_sin_feupdateenv);
+BIONIC_BENCHMARK(BM_math_sin_feupdateenv);
 
 static void BM_math_sin_fesetenv(benchmark::State& state) {
   d = 1.0;
@@ -176,7 +176,7 @@
     fesetenv(&__libc_save_rm);
   }
 }
-BENCHMARK(BM_math_sin_fesetenv);
+BIONIC_BENCHMARK(BM_math_sin_fesetenv);
 
 static void BM_math_fpclassify(benchmark::State& state) {
   d = 0.0;
@@ -186,7 +186,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_fpclassify);
+BIONIC_BENCHMARK(BM_math_fpclassify);
 
 static void BM_math_signbit_macro(benchmark::State& state) {
   d = 0.0;
@@ -196,7 +196,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_signbit_macro);
+BIONIC_BENCHMARK(BM_math_signbit_macro);
 
 static void BM_math_signbit(benchmark::State& state) {
   d = 0.0;
@@ -206,7 +206,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_signbit);
+BIONIC_BENCHMARK(BM_math_signbit);
 
 static void BM_math_fabs_macro(benchmark::State& state) {
   d = 0.0;
@@ -216,7 +216,7 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_fabs_macro);
+BIONIC_BENCHMARK(BM_math_fabs_macro);
 
 static void BM_math_fabs(benchmark::State& state) {
   d = 0.0;
@@ -226,4 +226,4 @@
   }
   SetLabel(state);
 }
-BENCHMARK_COMMON_VALS(BM_math_fabs);
+BIONIC_BENCHMARK(BM_math_fabs);
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 97eb832..a099494 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -27,11 +27,7 @@
 #include <sys/_system_properties.h>
 
 #include <benchmark/benchmark.h>
-
-// Do not exceed 512, that is about the largest number of properties
-// that can be created with the current property area size.
-#define TEST_NUM_PROPS \
-    Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
+#include "util.h"
 
 struct LocalPropertyTestState {
   explicit LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
@@ -145,7 +141,7 @@
     __system_property_get(pa.names[random() % nprops], value);
   }
 }
-BENCHMARK(BM_property_get)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_get);
 
 static void BM_property_find(benchmark::State& state) {
   const size_t nprops = state.range(0);
@@ -157,7 +153,7 @@
     __system_property_find(pa.names[random() % nprops]);
   }
 }
-BENCHMARK(BM_property_find)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_find);
 
 static void BM_property_read(benchmark::State& state) {
   const size_t nprops = state.range(0);
@@ -180,7 +176,7 @@
 
   delete[] pinfo;
 }
-BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_read);
 
 static void BM_property_serial(benchmark::State& state) {
   const size_t nprops = state.range(0);
@@ -201,6 +197,6 @@
 
   delete[] pinfo;
 }
-BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_serial);
 
 #endif  // __BIONIC__
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index d3c2de8..7a967ef 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -17,6 +17,7 @@
 #include <pthread.h>
 
 #include <benchmark/benchmark.h>
+#include "util.h"
 
 // Stop GCC optimizing out our pure function.
 /* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
@@ -26,7 +27,7 @@
     pthread_self_fp();
   }
 }
-BENCHMARK(BM_pthread_self);
+BIONIC_BENCHMARK(BM_pthread_self);
 
 static void BM_pthread_getspecific(benchmark::State& state) {
   pthread_key_t key;
@@ -38,7 +39,7 @@
 
   pthread_key_delete(key);
 }
-BENCHMARK(BM_pthread_getspecific);
+BIONIC_BENCHMARK(BM_pthread_getspecific);
 
 static void BM_pthread_setspecific(benchmark::State& state) {
   pthread_key_t key;
@@ -50,7 +51,7 @@
 
   pthread_key_delete(key);
 }
-BENCHMARK(BM_pthread_setspecific);
+BIONIC_BENCHMARK(BM_pthread_setspecific);
 
 static void DummyPthreadOnceInitFunction() {
 }
@@ -63,7 +64,7 @@
     pthread_once(&once, DummyPthreadOnceInitFunction);
   }
 }
-BENCHMARK(BM_pthread_once);
+BIONIC_BENCHMARK(BM_pthread_once);
 
 static void BM_pthread_mutex_lock(benchmark::State& state) {
   pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -73,7 +74,7 @@
     pthread_mutex_unlock(&mutex);
   }
 }
-BENCHMARK(BM_pthread_mutex_lock);
+BIONIC_BENCHMARK(BM_pthread_mutex_lock);
 
 static void BM_pthread_mutex_lock_ERRORCHECK(benchmark::State& state) {
   pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
@@ -83,7 +84,7 @@
     pthread_mutex_unlock(&mutex);
   }
 }
-BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
+BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
 
 static void BM_pthread_mutex_lock_RECURSIVE(benchmark::State& state) {
   pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
@@ -93,7 +94,7 @@
     pthread_mutex_unlock(&mutex);
   }
 }
-BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
+BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
 
 static void BM_pthread_rwlock_read(benchmark::State& state) {
   pthread_rwlock_t lock;
@@ -106,7 +107,7 @@
 
   pthread_rwlock_destroy(&lock);
 }
-BENCHMARK(BM_pthread_rwlock_read);
+BIONIC_BENCHMARK(BM_pthread_rwlock_read);
 
 static void BM_pthread_rwlock_write(benchmark::State& state) {
   pthread_rwlock_t lock;
@@ -119,7 +120,7 @@
 
   pthread_rwlock_destroy(&lock);
 }
-BENCHMARK(BM_pthread_rwlock_write);
+BIONIC_BENCHMARK(BM_pthread_rwlock_write);
 
 static void* IdleThread(void*) {
   return NULL;
@@ -134,7 +135,7 @@
     state.ResumeTiming();
   }
 }
-BENCHMARK(BM_pthread_create);
+BIONIC_BENCHMARK(BM_pthread_create);
 
 static void* RunThread(void* arg) {
   benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
@@ -150,7 +151,7 @@
     state.ResumeTiming();
   }
 }
-BENCHMARK(BM_pthread_create_and_run);
+BIONIC_BENCHMARK(BM_pthread_create_and_run);
 
 static void* ExitThread(void* arg) {
   benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
@@ -166,7 +167,7 @@
     pthread_join(thread, NULL);
   }
 }
-BENCHMARK(BM_pthread_exit_and_join);
+BIONIC_BENCHMARK(BM_pthread_exit_and_join);
 
 static void BM_pthread_key_create(benchmark::State& state) {
   while (state.KeepRunning()) {
@@ -178,7 +179,7 @@
     state.ResumeTiming();
   }
 }
-BENCHMARK(BM_pthread_key_create);
+BIONIC_BENCHMARK(BM_pthread_key_create);
 
 static void BM_pthread_key_delete(benchmark::State& state) {
   while (state.KeepRunning()) {
@@ -190,4 +191,4 @@
     pthread_key_delete(key);
   }
 }
-BENCHMARK(BM_pthread_key_delete);
+BIONIC_BENCHMARK(BM_pthread_key_delete);
diff --git a/benchmarks/semaphore_benchmark.cpp b/benchmarks/semaphore_benchmark.cpp
index b932a2b3..a4aa7bb 100644
--- a/benchmarks/semaphore_benchmark.cpp
+++ b/benchmarks/semaphore_benchmark.cpp
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 
 #include <benchmark/benchmark.h>
+#include "util.h"
 
 static void BM_semaphore_sem_getvalue(benchmark::State& state) {
   sem_t semaphore;
@@ -31,7 +32,7 @@
     sem_getvalue(&semaphore, &dummy);
   }
 }
-BENCHMARK(BM_semaphore_sem_getvalue);
+BIONIC_BENCHMARK(BM_semaphore_sem_getvalue);
 
 static void BM_semaphore_sem_wait_sem_post(benchmark::State& state) {
   sem_t semaphore;
@@ -42,7 +43,7 @@
     sem_post(&semaphore);
   }
 }
-BENCHMARK(BM_semaphore_sem_wait_sem_post);
+BIONIC_BENCHMARK(BM_semaphore_sem_wait_sem_post);
 
 // This test reports the overhead of the underlying futex wake syscall on
 // the producer. It does not report the overhead from issuing the wake to the
@@ -119,7 +120,9 @@
   bool setup = false;
 };
 
-BENCHMARK_F(SemaphoreFixture, semaphore_sem_post)(benchmark::State& state) {
+// This is commented out because dynamic benchmark registering doesn't currently support fixtures.
+// Uncomment it and recompile to run this benchmark on every run.
+/* BENCHMARK_F(SemaphoreFixture, semaphore_sem_post)(benchmark::State& state) {
   while (state.KeepRunning()) {
     state.PauseTiming();
 
@@ -149,4 +152,4 @@
     param.sched_priority = 0;
     sched_setscheduler(0, SCHED_IDLE, &param);
   }
-}
+}*/
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index f496779..2ab7264 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -14,17 +14,13 @@
  * limitations under the License.
  */
 
+#include <err.h>
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>
 
 #include <benchmark/benchmark.h>
-
-constexpr auto KB = 1024;
-
-#define AT_COMMON_SIZES \
-    Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(512)-> \
-    Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
+#include "util.h"
 
 template <typename Fn>
 void ReadWriteTest(benchmark::State& state, Fn f, bool buffered) {
@@ -50,29 +46,32 @@
 void BM_stdio_fread(benchmark::State& state) {
   ReadWriteTest(state, fread, true);
 }
-BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fread);
 
 void BM_stdio_fwrite(benchmark::State& state) {
   ReadWriteTest(state, fwrite, true);
 }
-BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fwrite);
 
 void BM_stdio_fread_unbuffered(benchmark::State& state) {
   ReadWriteTest(state, fread, false);
 }
-BENCHMARK(BM_stdio_fread_unbuffered)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fread_unbuffered);
 
 void BM_stdio_fwrite_unbuffered(benchmark::State& state) {
   ReadWriteTest(state, fwrite, false);
 }
-BENCHMARK(BM_stdio_fwrite_unbuffered)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fwrite_unbuffered);
 
 static void FopenFgetsFclose(benchmark::State& state, bool no_locking) {
-  char buf[1024];
+  size_t nbytes = state.range(0);
+  char buf[nbytes];
   while (state.KeepRunning()) {
-    FILE* fp = fopen("/proc/version", "re");
+    FILE* fp = fopen("/dev/zero", "re");
     if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
-    if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
+    if (fgets(buf, sizeof(buf), fp) == nullptr) {
+      errx(1, "ERROR:  fgets of %zu bytes failed.", nbytes);
+    }
     fclose(fp);
   }
 }
@@ -80,9 +79,33 @@
 static void BM_stdio_fopen_fgets_fclose_locking(benchmark::State& state) {
   FopenFgetsFclose(state, false);
 }
-BENCHMARK(BM_stdio_fopen_fgets_fclose_locking);
+BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_locking);
 
 void BM_stdio_fopen_fgets_fclose_no_locking(benchmark::State& state) {
   FopenFgetsFclose(state, true);
 }
-BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);
+BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);
+
+static void FopenFgetcFclose(benchmark::State& state, bool no_locking) {
+  size_t nbytes = state.range(0);
+  while (state.KeepRunning()) {
+    FILE* fp = fopen("/dev/zero", "re");
+    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
+    volatile int c __attribute__((unused));
+    for (size_t i = 0; i < nbytes; ++i) {
+      c = fgetc(fp);
+    }
+    fclose(fp);
+  }
+}
+
+static void BM_stdio_fopen_fgetc_fclose_locking(benchmark::State& state) {
+  FopenFgetcFclose(state, false);
+}
+BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_locking);
+
+void BM_stdio_fopen_fgetc_fclose_no_locking(benchmark::State& state) {
+  FopenFgetcFclose(state, true);
+}
+BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_no_locking);
+
diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp
new file mode 100644
index 0000000..eb325ab
--- /dev/null
+++ b/benchmarks/stdlib_benchmark.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <err.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <stdlib.h>
+
+#include <benchmark/benchmark.h>
+#include "util.h"
+
+static void BM_stdlib_malloc_free(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+
+  void* c;
+  while (state.KeepRunning()) {
+    c = malloc(nbytes);
+    free(c);
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BIONIC_BENCHMARK(BM_stdlib_malloc_free);
+
+static void BM_stdlib_mbstowcs(benchmark::State& state) {
+  const size_t buf_alignment = state.range(0);
+  const size_t widebuf_alignment = state.range(1);
+
+  std::vector<char> buf;
+  std::vector<wchar_t> widebuf;
+
+  setlocale(LC_CTYPE, "C.UTF-8")
+  || setlocale(LC_CTYPE, "en_US.UTF-8")
+  || setlocale(LC_CTYPE, "en_GB.UTF-8")
+  || setlocale(LC_CTYPE, "en.UTF-8")
+  || setlocale(LC_CTYPE, "de_DE-8")
+  || setlocale(LC_CTYPE, "fr_FR-8");
+  if (strcmp(nl_langinfo(CODESET), "UTF-8")) {
+    errx(1, "ERROR: unable to set locale in BM_stdlib_mbstowcs");
+  }
+
+  char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000);
+  wchar_t* widebuf_aligned = GetAlignedPtr(&widebuf, widebuf_alignment, 500000);
+  size_t i, j, k, l;
+  l = 0;
+  for (i=0xc3; i<0xe0; i++)
+    for (j=0x80; j<0xc0; j++)
+      buf[l++] = i, buf[l++] = j;
+  for (i=0xe1; i<0xed; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = k;
+  for (i=0xf1; i<0xf4; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k;
+  buf[l++] = 0;
+
+  volatile size_t c __attribute__((unused)) = 0;
+  while (state.KeepRunning()) {
+    c = mbstowcs(widebuf_aligned, buf_aligned, 500000);
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000));
+}
+BIONIC_BENCHMARK(BM_stdlib_mbstowcs);
+
+static void BM_stdlib_mbrtowc(benchmark::State& state) {
+  const size_t buf_alignment = state.range(0);
+
+  std::vector<char> buf;
+
+  setlocale(LC_CTYPE, "C.UTF-8")
+  || setlocale(LC_CTYPE, "en_US.UTF-8")
+  || setlocale(LC_CTYPE, "en_GB.UTF-8")
+  || setlocale(LC_CTYPE, "en.UTF-8")
+  || setlocale(LC_CTYPE, "de_DE-8")
+  || setlocale(LC_CTYPE, "fr_FR-8");
+  if (strcmp(nl_langinfo(CODESET), "UTF-8")) {
+    errx(1, "ERROR: unable to set locale in BM_stdlib_mbrtowc");
+  }
+
+  char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000);
+  size_t i, j, k, l;
+  l = 0;
+  for (i=0xc3; i<0xe0; i++)
+    for (j=0x80; j<0xc0; j++)
+      buf[l++] = i, buf[l++] = j;
+  for (i=0xe1; i<0xed; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = k;
+  for (i=0xf1; i<0xf4; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k;
+  buf[l++] = 0;
+
+  wchar_t wc = 0;
+  while (state.KeepRunning()) {
+    for (j = 0; buf_aligned[j]; j+=mbrtowc(&wc, buf_aligned + j, 4, NULL)) {
+    }
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000));
+}
+BIONIC_BENCHMARK(BM_stdlib_mbrtowc);
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index 2ab65a8..eb04c93 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -14,31 +14,12 @@
  * limitations under the License.
  */
 
+#include <err.h>
 #include <stdint.h>
 #include <string.h>
 
 #include <benchmark/benchmark.h>
-#include "util.h"
-
-constexpr auto KB = 1024;
-
-// NOTE: these constants are temporary replacements for AT_COMMON_SIZES until
-// the new interface for Bionic benchmarks is implemented.
-
-// Set all four to 0 to test normal alignment.
-#define AT_SRC_ALIGN 0
-#define AT_DST_ALIGN 0
-
-#define AT_ALIGNED_TWOBUF \
-    Args({(8), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
-    Args({(512), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(1*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
-    Args({(8*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(16*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
-    Args({(32*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64*KB), AT_SRC_ALIGN, AT_DST_ALIGN})
-
-#define AT_ALIGNED_ONEBUF \
-    Args({(8), AT_SRC_ALIGN})->Args({(64), AT_SRC_ALIGN})->Args({(512), AT_SRC_ALIGN})-> \
-    Args({(1*KB), AT_SRC_ALIGN})->Args({(8*KB), AT_SRC_ALIGN})->Args({(16*KB), AT_SRC_ALIGN})-> \
-    Args({(32*KB), AT_SRC_ALIGN})->Args({(64*KB), AT_SRC_ALIGN})
+#include <util.h>
 
 static void BM_string_memcmp(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -57,7 +38,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_memcmp)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_memcmp);
 
 static void BM_string_memcpy(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -75,7 +56,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_memcpy)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_memcpy);
 
 static void BM_string_memmove_non_overlapping(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -93,7 +74,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_memmove_non_overlapping)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_memmove_non_overlapping);
 
 static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -108,7 +89,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_memmove_overlap_dst_before_src)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_memmove_overlap_dst_before_src);
 
 static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -123,7 +104,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_memmove_overlap_src_before_dst)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_memmove_overlap_src_before_dst);
 
 static void BM_string_memset(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -138,7 +119,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_memset)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_memset);
 
 static void BM_string_strlen(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -155,7 +136,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_strlen)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_strlen);
 
 static void BM_string_strcat_copy_only(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -178,7 +159,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_strcat_copy_only)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcat_copy_only);
 
 static void BM_string_strcat_seek_only(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -199,7 +180,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_strcat_seek_only)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcat_seek_only);
 
 static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -220,7 +201,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_strcat_half_copy_half_seek)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcat_half_copy_half_seek);
 
 static void BM_string_strcpy(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -239,7 +220,7 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_strcpy)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcpy);
 
 static void BM_string_strcmp(benchmark::State& state) {
   const size_t nbytes = state.range(0);
@@ -260,4 +241,51 @@
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
-BENCHMARK(BM_string_strcmp)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcmp);
+
+static void BM_string_strstr(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t haystack_alignment = state.range(1);
+  const size_t needle_alignment = state.range(2);
+
+  std::vector<char> haystack;
+  std::vector<char> needle;
+  char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
+  char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment,
+                                             std::min(nbytes, static_cast<size_t>(5)), 'x');
+
+  if (nbytes / 4 > 2) {
+    for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) {
+      haystack_aligned[4 * i + 3] = 'y';
+    }
+  }
+  haystack_aligned[nbytes - 1] = '\0';
+  needle_aligned[needle.size() - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    if (strstr(haystack_aligned, needle_aligned) == nullptr) {
+      errx(1, "ERROR: strstr failed to find valid substring.");
+    }
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BIONIC_BENCHMARK(BM_string_strstr);
+
+static void BM_string_strchr(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t haystack_alignment = state.range(1);
+
+  std::vector<char> haystack;
+  char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
+  haystack_aligned[nbytes-1] = '\0';
+
+  while (state.KeepRunning()) {
+    if (strchr(haystack_aligned, 'y') != nullptr) {
+      errx(1, "ERROR: strchr found a chr where it should have failed.");
+    }
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BIONIC_BENCHMARK(BM_string_strchr);
diff --git a/benchmarks/suites/full.xml b/benchmarks/suites/full.xml
new file mode 100644
index 0000000..8c9aef6
--- /dev/null
+++ b/benchmarks/suites/full.xml
@@ -0,0 +1,297 @@
+<fn>
+  <name>BM_empty</name>
+</fn>
+<fn>
+  <name>BM_load_relaxed</name>
+</fn>
+<fn>
+  <name>BM_load_acquire</name>
+</fn>
+<fn>
+  <name>BM_store_release</name>
+</fn>
+<fn>
+  <name>BM_store_seq_cst</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_relaxed</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_seq_cst</name>
+</fn>
+<fn>
+  <name>BM_acquire_fence</name>
+</fn>
+<fn>
+  <name>BM_seq_cst_fence</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_cs</name>
+</fn>
+<fn>
+  <name>BM_math_sqrt</name>
+</fn>
+<fn>
+  <name>BM_math_log10</name>
+</fn>
+<fn>
+  <name>BM_math_logb</name>
+</fn>
+<fn>
+  <name>BM_math_isfinite_macro</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_isfinite</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_isinf_macro</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_isinf</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_isnan_macro</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_isnan</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_isnormal_macro</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_isnormal</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_sin_fast</name>
+</fn>
+<fn>
+  <name>BM_math_sin_feupdateenv</name>
+</fn>
+<fn>
+  <name>BM_math_sin_fesetenv</name>
+</fn>
+<fn>
+  <name>BM_math_fpclassify</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_signbit_macro</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_signbit</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_fabs_macro</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_math_fabs</name>
+  <args>MATH_COMMON</args>
+</fn>
+<fn>
+  <name>BM_property_get</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_property_find</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_property_read</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_property_serial</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_pthread_self</name>
+</fn>
+<fn>
+  <name>BM_pthread_getspecific</name>
+</fn>
+<fn>
+  <name>BM_pthread_setspecific</name>
+</fn>
+<fn>
+  <name>BM_pthread_once</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock_ERRORCHECK</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock_RECURSIVE</name>
+</fn>
+<fn>
+  <name>BM_pthread_rwlock_read</name>
+</fn>
+<fn>
+  <name>BM_pthread_rwlock_write</name>
+</fn>
+<fn>
+  <name>BM_pthread_create</name>
+</fn>
+<fn>
+  <name>BM_pthread_create_and_run</name>
+</fn>
+<fn>
+  <name>BM_pthread_exit_and_join</name>
+</fn>
+<fn>
+  <name>BM_pthread_key_create</name>
+</fn>
+<fn>
+  <name>BM_pthread_key_delete</name>
+</fn>
+<fn>
+  <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+  <name>BM_semaphore_sem_wait_sem_post</name>
+</fn>
+<fn>
+  <name>BM_stdio_fread</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fwrite</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fread_unbuffered</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fwrite_unbuffered</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgets_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_string_memcmp</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memcpy</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_non_overlapping</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_overlap_dst_before_src</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_overlap_src_before_dst</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memset</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_copy_only</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_seek_only</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_half_copy_half_seek</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcpy</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcmp</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strstr</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strchr</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_time</name>
+</fn>
+<fn>
+  <name>BM_time_localtime</name>
+</fn>
+<fn>
+  <name>BM_time_localtime_r</name>
+</fn>
+<fn>
+  <name>BM_unistd_getpid</name>
+</fn>
+<fn>
+  <name>BM_unistd_getpid_syscall</name>
+</fn>
+<fn>
+  <name>BM_unistd_gettid</name>
+</fn>
+<fn>
+  <name>BM_unistd_gettid_syscall</name>
+</fn>
+<fn>
+  <name>BM_stdlib_malloc_free</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbstowcs</name>
+  <args>0 0</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbrtowc</name>
+  <args>0</args>
+</fn>
diff --git a/benchmarks/suites/host.xml b/benchmarks/suites/host.xml
new file mode 100644
index 0000000..05769e9
--- /dev/null
+++ b/benchmarks/suites/host.xml
@@ -0,0 +1,274 @@
+<fn>
+  <name>BM_empty</name>
+</fn>
+<fn>
+  <name>BM_load_relaxed</name>
+</fn>
+<fn>
+  <name>BM_load_acquire</name>
+</fn>
+<fn>
+  <name>BM_store_release</name>
+</fn>
+<fn>
+  <name>BM_store_seq_cst</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_relaxed</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_seq_cst</name>
+</fn>
+<fn>
+  <name>BM_acquire_fence</name>
+</fn>
+<fn>
+  <name>BM_seq_cst_fence</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_cs</name>
+</fn>
+<fn>
+  <name>BM_math_sqrt</name>
+</fn>
+<fn>
+  <name>BM_math_log10</name>
+</fn>
+<fn>
+  <name>BM_math_logb</name>
+</fn>
+<fn>
+  <name>BM_math_isfinite_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isfinite</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isinf_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isinf</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isnan_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isnan</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isnormal_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_sin_fast</name>
+</fn>
+<fn>
+  <name>BM_math_sin_feupdateenv</name>
+</fn>
+<fn>
+  <name>BM_math_sin_fesetenv</name>
+</fn>
+<fn>
+  <name>BM_math_fpclassify</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_signbit_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_signbit</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_fabs_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_fabs</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_pthread_self</name>
+</fn>
+<fn>
+  <name>BM_pthread_getspecific</name>
+</fn>
+<fn>
+  <name>BM_pthread_setspecific</name>
+</fn>
+<fn>
+  <name>BM_pthread_once</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock_ERRORCHECK</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock_RECURSIVE</name>
+</fn>
+<fn>
+  <name>BM_pthread_rwlock_read</name>
+</fn>
+<fn>
+  <name>BM_pthread_rwlock_write</name>
+</fn>
+<fn>
+  <name>BM_pthread_create</name>
+</fn>
+<fn>
+  <name>BM_pthread_create_and_run</name>
+</fn>
+<fn>
+  <name>BM_pthread_exit_and_join</name>
+</fn>
+<fn>
+  <name>BM_pthread_key_create</name>
+</fn>
+<fn>
+  <name>BM_pthread_key_delete</name>
+</fn>
+<fn>
+  <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+  <name>BM_semaphore_sem_wait_sem_post</name>
+</fn>
+<fn>
+  <name>BM_stdio_fread</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fwrite</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fread_unbuffered</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fwrite_unbuffered</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgets_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_string_memcmp</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memcpy</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_non_overlapping</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_overlap_dst_before_src</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_overlap_src_before_dst</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memset</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_copy_only</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_seek_only</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_half_copy_half_seek</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcpy</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcmp</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strstr</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strchr</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_time</name>
+</fn>
+<fn>
+  <name>BM_time_localtime</name>
+</fn>
+<fn>
+  <name>BM_time_localtime_r</name>
+</fn>
+<fn>
+  <name>BM_unistd_getpid</name>
+</fn>
+<fn>
+  <name>BM_unistd_getpid_syscall</name>
+</fn>
+<fn>
+  <name>BM_unistd_gettid_syscall</name>
+</fn>
+<fn>
+  <name>BM_stdlib_malloc_free</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbstowcs</name>
+  <args>0 0</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbrtowc</name>
+  <args>0</args>
+</fn>
diff --git a/benchmarks/suites/test_alignment.xml b/benchmarks/suites/test_alignment.xml
new file mode 100644
index 0000000..20df320
--- /dev/null
+++ b/benchmarks/suites/test_alignment.xml
@@ -0,0 +1,50 @@
+<fn>
+  <name>BM_string_memcmp</name>
+  <iterations>1</iterations>
+  <args>AT_2_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memcmp</name>
+  <iterations>1</iterations>
+  <args>AT_4_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memcmp</name>
+  <iterations>1</iterations>
+  <args>AT_16_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memcmp</name>
+  <iterations>1</iterations>
+  <args>AT_512_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memcmp</name>
+  <iterations>1</iterations>
+  <args>AT_2048_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <iterations>1</iterations>
+  <args>AT_2_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <iterations>1</iterations>
+  <args>AT_4_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <iterations>1</iterations>
+  <args>AT_16_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <iterations>1</iterations>
+  <args>AT_512_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <iterations>1</iterations>
+  <args>AT_2048_ALIGN_ONEBUF</args>
+</fn>
diff --git a/benchmarks/suites/test_from_each.xml b/benchmarks/suites/test_from_each.xml
new file mode 100644
index 0000000..0118365
--- /dev/null
+++ b/benchmarks/suites/test_from_each.xml
@@ -0,0 +1,30 @@
+<fn>
+  <name>BM_empty</name>
+</fn>
+<fn>
+  <name>BM_math_sqrt</name>
+</fn>
+<fn>
+  <name>BM_property_get</name>
+  <args>1</args>
+</fn>
+<fn>
+  <name>BM_pthread_self</name>
+</fn>
+<fn>
+  <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+  <name>BM_stdio_fread</name>
+  <args>64</args>
+</fn>
+<fn>
+  <name>BM_string_memcpy</name>
+  <args>512 4 4</args>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+  <name>BM_unistd_getpid</name>
+</fn>
diff --git a/benchmarks/suites/test_full.xml b/benchmarks/suites/test_full.xml
new file mode 100644
index 0000000..adc3f28
--- /dev/null
+++ b/benchmarks/suites/test_full.xml
@@ -0,0 +1,291 @@
+<fn>
+  <name>BM_empty</name>
+</fn>
+<fn>
+  <name>BM_load_relaxed</name>
+</fn>
+<fn>
+  <name>BM_load_acquire</name>
+</fn>
+<fn>
+  <name>BM_store_release</name>
+</fn>
+<fn>
+  <name>BM_store_seq_cst</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_relaxed</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_seq_cst</name>
+</fn>
+<fn>
+  <name>BM_acquire_fence</name>
+</fn>
+<fn>
+  <name>BM_seq_cst_fence</name>
+</fn>
+<fn>
+  <name>BM_fetch_add_cs</name>
+</fn>
+<fn>
+  <name>BM_math_sqrt</name>
+</fn>
+<fn>
+  <name>BM_math_log10</name>
+</fn>
+<fn>
+  <name>BM_math_logb</name>
+</fn>
+<fn>
+  <name>BM_math_isfinite_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isfinite</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isinf_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isinf</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isnan_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isnan</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isnormal_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_isnormal</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_sin_fast</name>
+</fn>
+<fn>
+  <name>BM_math_sin_feupdateenv</name>
+</fn>
+<fn>
+  <name>BM_math_sin_fesetenv</name>
+</fn>
+<fn>
+  <name>BM_math_fpclassify</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_signbit_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_signbit</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_fabs_macro</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_math_fabs</name>
+  <args>0</args>
+</fn>
+<fn>
+  <name>BM_property_get</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_property_find</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_property_read</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_property_serial</name>
+  <args>NUM_PROPS</args>
+</fn>
+<fn>
+  <name>BM_pthread_self</name>
+</fn>
+<fn>
+  <name>BM_pthread_getspecific</name>
+</fn>
+<fn>
+  <name>BM_pthread_setspecific</name>
+</fn>
+<fn>
+  <name>BM_pthread_once</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock_ERRORCHECK</name>
+</fn>
+<fn>
+  <name>BM_pthread_mutex_lock_RECURSIVE</name>
+</fn>
+<fn>
+  <name>BM_pthread_rwlock_read</name>
+</fn>
+<fn>
+  <name>BM_pthread_rwlock_write</name>
+</fn>
+<fn>
+  <name>BM_pthread_create</name>
+</fn>
+<fn>
+  <name>BM_pthread_create_and_run</name>
+</fn>
+<fn>
+  <name>BM_pthread_exit_and_join</name>
+</fn>
+<fn>
+  <name>BM_pthread_key_create</name>
+</fn>
+<fn>
+  <name>BM_pthread_key_delete</name>
+</fn>
+<fn>
+  <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+  <name>BM_semaphore_sem_wait_sem_post</name>
+</fn>
+<fn>
+  <name>BM_stdio_fread</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fwrite</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fread_unbuffered</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fwrite_unbuffered</name>
+  <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgets_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_string_memcmp</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memcpy</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_non_overlapping</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_overlap_dst_before_src</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memmove_overlap_src_before_dst</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_memset</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strlen</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_copy_only</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_seek_only</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcat_half_copy_half_seek</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcpy</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strcmp</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strstr</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strchr</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+  <name>BM_time_clock_gettime_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday</name>
+</fn>
+<fn>
+  <name>BM_time_gettimeofday_syscall</name>
+</fn>
+<fn>
+  <name>BM_time_time</name>
+</fn>
+<fn>
+  <name>BM_unistd_getpid</name>
+</fn>
+<fn>
+  <name>BM_unistd_getpid_syscall</name>
+</fn>
+<fn>
+  <name>BM_unistd_gettid</name>
+</fn>
+<fn>
+  <name>BM_unistd_gettid_syscall</name>
+</fn>
+<fn>
+  <name>BM_stdlib_malloc_free</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbstowcs</name>
+  <args>0 0</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbrtowc</name>
+  <args>0</args>
+</fn>
diff --git a/benchmarks/suites/test_medium.xml b/benchmarks/suites/test_medium.xml
new file mode 100644
index 0000000..9528af3
--- /dev/null
+++ b/benchmarks/suites/test_medium.xml
@@ -0,0 +1,16 @@
+<fn>
+  <name>BM_string_memcmp</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_math_sqrt</name>
+</fn>
+<fn>
+  <name>BM_string_memcpy</name>
+  <iterations>25</iterations>
+  <args>512 4 4</args>
+</fn>
+<fn>
+  <name>BM_property_get</name>
+  <args>1</args>
+</fn>
diff --git a/benchmarks/suites/test_small.xml b/benchmarks/suites/test_small.xml
new file mode 100644
index 0000000..a4cc285
--- /dev/null
+++ b/benchmarks/suites/test_small.xml
@@ -0,0 +1,11 @@
+<fn>
+  <name>BM_string_memcmp</name>
+  <args>8 8 8</args>
+</fn>
+<fn>
+  <name>BM_math_sqrt</name>
+</fn>
+<fn>
+  <name>BM_property_get</name>
+  <args>1</args>
+</fn>
diff --git a/benchmarks/tests/interface_test.cpp b/benchmarks/tests/interface_test.cpp
new file mode 100644
index 0000000..9283e6b
--- /dev/null
+++ b/benchmarks/tests/interface_test.cpp
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <regex>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+class SystemTests : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    raw_output_ = "";
+    sanitized_output_ = "";
+    exitcode_ = 0;
+  }
+
+  void SanitizeOutput();
+
+  void Exec(std::vector<const char*> args);
+  void ExecAndCapture(std::vector<const char*> args);
+  void RunTest(std::vector<const char*> extra_args = {});
+  void Verify(const std::string& expected_output, int expected_exitcode,
+              std::vector<const char*> extra_args = {});
+
+  std::string raw_output_;
+  std::string sanitized_output_;
+  int exitcode_;
+  pid_t pid_;
+  int fd_;
+};
+
+void SystemTests::SanitizeOutput() {
+  // Cut off anything after the arguments, since that varies with time.
+  sanitized_output_ = std::regex_replace(raw_output_, std::regex(".+(BM_\\S+) +.+"), "$1");
+
+  // Remove everything before the header.
+  sanitized_output_.erase(0, sanitized_output_.find("------------------------------------------------"));
+
+  // Remove the header.
+  sanitized_output_.erase(0, sanitized_output_.find("BM_"));
+
+  // Remove any hanging output.
+  sanitized_output_.erase(sanitized_output_.find_last_of("BM_\\S+\n") + 1);
+}
+
+static void GetExe(std::string* exe_name) {
+  char path[PATH_MAX];
+  ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+  ASSERT_TRUE(path_len >= 0);
+  *exe_name = std::string(std::regex_replace(path, std::regex("-tests"), ""));
+}
+
+void SystemTests::Exec(std::vector<const char*> args) {
+  int fds[2];
+  ASSERT_NE(-1, pipe(fds));
+  ASSERT_NE(-1, fcntl(fds[0], F_SETFL, O_NONBLOCK));
+
+  if ((pid_ = fork()) == 0) {
+    // Run the test.
+    close(fds[0]);
+    close(STDIN_FILENO);
+    close(STDOUT_FILENO);
+    close(STDERR_FILENO);
+    ASSERT_NE(0, dup2(fds[1], STDOUT_FILENO));
+    ASSERT_NE(0, dup2(fds[1], STDERR_FILENO));
+    close(fds[1]);
+
+    std::string exe_name;
+    GetExe(&exe_name);
+    args.insert(args.begin(), exe_name.c_str());
+    args.push_back(nullptr);
+    execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
+    exit(1);
+  }
+  ASSERT_NE(-1, pid_);
+
+  close(fds[1]);
+  fd_ = fds[0];
+}
+
+void SystemTests::Verify(const std::string& expected_output,
+                         int expected_exitcode, std::vector<const char*> extra_args) {
+  std::vector<const char*> args;
+  for (const auto& arg : extra_args) {
+    args.push_back(arg);
+  }
+
+  Exec(args);
+
+  raw_output_ = "";
+  while (true) {
+    char buffer[4097];
+    ssize_t bytes = TEMP_FAILURE_RETRY(read(fd_, buffer, sizeof(buffer) - 1));
+    if (bytes == -1 && errno == EAGAIN) {
+      continue;
+    }
+    ASSERT_NE(-1, bytes);
+    if (bytes == 0) {
+      break;
+    }
+    buffer[bytes] = '\0';
+    raw_output_ += buffer;
+  }
+  close(fd_);
+
+  int status;
+  ASSERT_EQ(pid_, TEMP_FAILURE_RETRY(waitpid(pid_, &status, 0))) << "Test output:\n" << raw_output_;
+  exitcode_ = WEXITSTATUS(status);
+  SanitizeOutput();
+
+  ASSERT_EQ(expected_exitcode, exitcode_) << "Test output:\n" << raw_output_;
+  if (!expected_output.empty()) {
+    ASSERT_EQ(expected_output, sanitized_output_);
+  }
+
+}
+
+TEST_F(SystemTests, full_suite) {
+  std::string expected =
+    "BM_empty/iterations:1\n"
+    "BM_load_relaxed/iterations:1\n"
+    "BM_load_acquire/iterations:1\n"
+    "BM_store_release/iterations:1\n"
+    "BM_store_seq_cst/iterations:1\n"
+    "BM_fetch_add_relaxed/iterations:1\n"
+    "BM_fetch_add_seq_cst/iterations:1\n"
+    "BM_acquire_fence/iterations:1\n"
+    "BM_seq_cst_fence/iterations:1\n"
+    "BM_fetch_add_cs/iterations:1\n"
+    "BM_math_sqrt/iterations:1\n"
+    "BM_math_log10/iterations:1\n"
+    "BM_math_logb/iterations:1\n"
+    "BM_math_isfinite_macro/0/iterations:1\n"
+    "BM_math_isfinite/0/iterations:1\n"
+    "BM_math_isinf_macro/0/iterations:1\n"
+    "BM_math_isinf/0/iterations:1\n"
+    "BM_math_isnan_macro/0/iterations:1\n"
+    "BM_math_isnan/0/iterations:1\n"
+    "BM_math_isnormal_macro/0/iterations:1\n"
+    "BM_math_isnormal/0/iterations:1\n"
+    "BM_math_sin_fast/iterations:1\n"
+    "BM_math_sin_feupdateenv/iterations:1\n"
+    "BM_math_sin_fesetenv/iterations:1\n"
+    "BM_math_fpclassify/0/iterations:1\n"
+    "BM_math_signbit_macro/0/iterations:1\n"
+    "BM_math_signbit/0/iterations:1\n"
+    "BM_math_fabs_macro/0/iterations:1\n"
+    "BM_math_fabs/0/iterations:1\n"
+    "BM_property_get/1/iterations:1\n"
+    "BM_property_get/4/iterations:1\n"
+    "BM_property_get/16/iterations:1\n"
+    "BM_property_get/64/iterations:1\n"
+    "BM_property_get/128/iterations:1\n"
+    "BM_property_get/256/iterations:1\n"
+    "BM_property_get/512/iterations:1\n"
+    "BM_property_find/1/iterations:1\n"
+    "BM_property_find/4/iterations:1\n"
+    "BM_property_find/16/iterations:1\n"
+    "BM_property_find/64/iterations:1\n"
+    "BM_property_find/128/iterations:1\n"
+    "BM_property_find/256/iterations:1\n"
+    "BM_property_find/512/iterations:1\n"
+    "BM_property_read/1/iterations:1\n"
+    "BM_property_read/4/iterations:1\n"
+    "BM_property_read/16/iterations:1\n"
+    "BM_property_read/64/iterations:1\n"
+    "BM_property_read/128/iterations:1\n"
+    "BM_property_read/256/iterations:1\n"
+    "BM_property_read/512/iterations:1\n"
+    "BM_property_serial/1/iterations:1\n"
+    "BM_property_serial/4/iterations:1\n"
+    "BM_property_serial/16/iterations:1\n"
+    "BM_property_serial/64/iterations:1\n"
+    "BM_property_serial/128/iterations:1\n"
+    "BM_property_serial/256/iterations:1\n"
+    "BM_property_serial/512/iterations:1\n"
+    "BM_pthread_self/iterations:1\n"
+    "BM_pthread_getspecific/iterations:1\n"
+    "BM_pthread_setspecific/iterations:1\n"
+    "BM_pthread_once/iterations:1\n"
+    "BM_pthread_mutex_lock/iterations:1\n"
+    "BM_pthread_mutex_lock_ERRORCHECK/iterations:1\n"
+    "BM_pthread_mutex_lock_RECURSIVE/iterations:1\n"
+    "BM_pthread_rwlock_read/iterations:1\n"
+    "BM_pthread_rwlock_write/iterations:1\n"
+    "BM_pthread_create/iterations:1\n"
+    "BM_pthread_create_and_run/iterations:1\n"
+    "BM_pthread_exit_and_join/iterations:1\n"
+    "BM_pthread_key_create/iterations:1\n"
+    "BM_pthread_key_delete/iterations:1\n"
+    "BM_semaphore_sem_getvalue/iterations:1\n"
+    "BM_semaphore_sem_wait_sem_post/iterations:1\n"
+    "BM_stdio_fread/8/iterations:1\n"
+    "BM_stdio_fread/64/iterations:1\n"
+    "BM_stdio_fread/512/iterations:1\n"
+    "BM_stdio_fread/1024/iterations:1\n"
+    "BM_stdio_fread/8192/iterations:1\n"
+    "BM_stdio_fread/16384/iterations:1\n"
+    "BM_stdio_fread/32768/iterations:1\n"
+    "BM_stdio_fread/65536/iterations:1\n"
+    "BM_stdio_fwrite/8/iterations:1\n"
+    "BM_stdio_fwrite/64/iterations:1\n"
+    "BM_stdio_fwrite/512/iterations:1\n"
+    "BM_stdio_fwrite/1024/iterations:1\n"
+    "BM_stdio_fwrite/8192/iterations:1\n"
+    "BM_stdio_fwrite/16384/iterations:1\n"
+    "BM_stdio_fwrite/32768/iterations:1\n"
+    "BM_stdio_fwrite/65536/iterations:1\n"
+    "BM_stdio_fread_unbuffered/8/iterations:1\n"
+    "BM_stdio_fread_unbuffered/64/iterations:1\n"
+    "BM_stdio_fread_unbuffered/512/iterations:1\n"
+    "BM_stdio_fread_unbuffered/1024/iterations:1\n"
+    "BM_stdio_fread_unbuffered/8192/iterations:1\n"
+    "BM_stdio_fread_unbuffered/16384/iterations:1\n"
+    "BM_stdio_fread_unbuffered/32768/iterations:1\n"
+    "BM_stdio_fread_unbuffered/65536/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/8/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/64/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/512/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/1024/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/8192/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/16384/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/32768/iterations:1\n"
+    "BM_stdio_fwrite_unbuffered/65536/iterations:1\n"
+    "BM_stdio_fopen_fgets_fclose_locking/1024/iterations:1\n"
+    "BM_stdio_fopen_fgets_fclose_no_locking/1024/iterations:1\n"
+    "BM_stdio_fopen_fgetc_fclose_locking/1024/iterations:1\n"
+    "BM_stdio_fopen_fgetc_fclose_no_locking/1024/iterations:1\n"
+    "BM_string_memcmp/8/0/0/iterations:1\n"
+    "BM_string_memcmp/64/0/0/iterations:1\n"
+    "BM_string_memcmp/512/0/0/iterations:1\n"
+    "BM_string_memcmp/1024/0/0/iterations:1\n"
+    "BM_string_memcmp/8192/0/0/iterations:1\n"
+    "BM_string_memcmp/16384/0/0/iterations:1\n"
+    "BM_string_memcmp/32768/0/0/iterations:1\n"
+    "BM_string_memcmp/65536/0/0/iterations:1\n"
+    "BM_string_memcpy/8/0/0/iterations:1\n"
+    "BM_string_memcpy/64/0/0/iterations:1\n"
+    "BM_string_memcpy/512/0/0/iterations:1\n"
+    "BM_string_memcpy/1024/0/0/iterations:1\n"
+    "BM_string_memcpy/8192/0/0/iterations:1\n"
+    "BM_string_memcpy/16384/0/0/iterations:1\n"
+    "BM_string_memcpy/32768/0/0/iterations:1\n"
+    "BM_string_memcpy/65536/0/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/8/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/64/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/512/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/1024/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/8192/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/16384/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/32768/0/iterations:1\n"
+    "BM_string_memmove_non_overlapping/65536/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/8/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/64/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/512/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/1024/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/8192/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/16384/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/32768/0/iterations:1\n"
+    "BM_string_memmove_overlap_dst_before_src/65536/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/8/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/64/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/512/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/1024/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/8192/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/16384/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/32768/0/iterations:1\n"
+    "BM_string_memmove_overlap_src_before_dst/65536/0/iterations:1\n"
+    "BM_string_memset/8/0/iterations:1\n"
+    "BM_string_memset/64/0/iterations:1\n"
+    "BM_string_memset/512/0/iterations:1\n"
+    "BM_string_memset/1024/0/iterations:1\n"
+    "BM_string_memset/8192/0/iterations:1\n"
+    "BM_string_memset/16384/0/iterations:1\n"
+    "BM_string_memset/32768/0/iterations:1\n"
+    "BM_string_memset/65536/0/iterations:1\n"
+    "BM_string_strlen/8/0/iterations:1\n"
+    "BM_string_strlen/64/0/iterations:1\n"
+    "BM_string_strlen/512/0/iterations:1\n"
+    "BM_string_strlen/1024/0/iterations:1\n"
+    "BM_string_strlen/8192/0/iterations:1\n"
+    "BM_string_strlen/16384/0/iterations:1\n"
+    "BM_string_strlen/32768/0/iterations:1\n"
+    "BM_string_strlen/65536/0/iterations:1\n"
+    "BM_string_strcat_copy_only/8/0/0/iterations:1\n"
+    "BM_string_strcat_copy_only/64/0/0/iterations:1\n"
+    "BM_string_strcat_copy_only/512/0/0/iterations:1\n"
+    "BM_string_strcat_copy_only/1024/0/0/iterations:1\n"
+    "BM_string_strcat_copy_only/8192/0/0/iterations:1\n"
+    "BM_string_strcat_copy_only/16384/0/0/iterations:1\n"
+    "BM_string_strcat_copy_only/32768/0/0/iterations:1\n"
+    "BM_string_strcat_copy_only/65536/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/8/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/64/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/512/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/1024/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/8192/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/16384/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/32768/0/0/iterations:1\n"
+    "BM_string_strcat_seek_only/65536/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/8/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/64/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/512/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/1024/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/8192/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/16384/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/32768/0/0/iterations:1\n"
+    "BM_string_strcat_half_copy_half_seek/65536/0/0/iterations:1\n"
+    "BM_string_strcpy/8/0/0/iterations:1\n"
+    "BM_string_strcpy/64/0/0/iterations:1\n"
+    "BM_string_strcpy/512/0/0/iterations:1\n"
+    "BM_string_strcpy/1024/0/0/iterations:1\n"
+    "BM_string_strcpy/8192/0/0/iterations:1\n"
+    "BM_string_strcpy/16384/0/0/iterations:1\n"
+    "BM_string_strcpy/32768/0/0/iterations:1\n"
+    "BM_string_strcpy/65536/0/0/iterations:1\n"
+    "BM_string_strcmp/8/0/0/iterations:1\n"
+    "BM_string_strcmp/64/0/0/iterations:1\n"
+    "BM_string_strcmp/512/0/0/iterations:1\n"
+    "BM_string_strcmp/1024/0/0/iterations:1\n"
+    "BM_string_strcmp/8192/0/0/iterations:1\n"
+    "BM_string_strcmp/16384/0/0/iterations:1\n"
+    "BM_string_strcmp/32768/0/0/iterations:1\n"
+    "BM_string_strcmp/65536/0/0/iterations:1\n"
+    "BM_string_strstr/8/0/0/iterations:1\n"
+    "BM_string_strstr/64/0/0/iterations:1\n"
+    "BM_string_strstr/512/0/0/iterations:1\n"
+    "BM_string_strstr/1024/0/0/iterations:1\n"
+    "BM_string_strstr/8192/0/0/iterations:1\n"
+    "BM_string_strstr/16384/0/0/iterations:1\n"
+    "BM_string_strstr/32768/0/0/iterations:1\n"
+    "BM_string_strstr/65536/0/0/iterations:1\n"
+    "BM_string_strchr/8/0/iterations:1\n"
+    "BM_string_strchr/64/0/iterations:1\n"
+    "BM_string_strchr/512/0/iterations:1\n"
+    "BM_string_strchr/1024/0/iterations:1\n"
+    "BM_string_strchr/8192/0/iterations:1\n"
+    "BM_string_strchr/16384/0/iterations:1\n"
+    "BM_string_strchr/32768/0/iterations:1\n"
+    "BM_string_strchr/65536/0/iterations:1\n"
+    "BM_time_clock_gettime/iterations:1\n"
+    "BM_time_clock_gettime_syscall/iterations:1\n"
+    "BM_time_gettimeofday/iterations:1\n"
+    "BM_time_gettimeofday_syscall/iterations:1\n"
+    "BM_time_time/iterations:1\n"
+    "BM_unistd_getpid/iterations:1\n"
+    "BM_unistd_getpid_syscall/iterations:1\n"
+    "BM_unistd_gettid/iterations:1\n"
+    "BM_unistd_gettid_syscall/iterations:1\n"
+    "BM_stdlib_malloc_free/8/0/iterations:1\n"
+    "BM_stdlib_malloc_free/64/0/iterations:1\n"
+    "BM_stdlib_malloc_free/512/0/iterations:1\n"
+    "BM_stdlib_malloc_free/1024/0/iterations:1\n"
+    "BM_stdlib_malloc_free/8192/0/iterations:1\n"
+    "BM_stdlib_malloc_free/16384/0/iterations:1\n"
+    "BM_stdlib_malloc_free/32768/0/iterations:1\n"
+    "BM_stdlib_malloc_free/65536/0/iterations:1\n"
+    "BM_stdlib_mbstowcs/0/0/iterations:1\n"
+    "BM_stdlib_mbrtowc/0/iterations:1\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_full.xml",
+                                                "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, small) {
+  std::string expected =
+    "BM_string_memcmp/8/8/8\n"
+    "BM_math_sqrt\n"
+    "BM_property_get/1\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_small.xml"});
+}
+
+TEST_F(SystemTests, medium) {
+  std::string expected =
+    "BM_string_memcmp/8/0/0/iterations:1\n"
+    "BM_string_memcmp/64/0/0/iterations:1\n"
+    "BM_string_memcmp/512/0/0/iterations:1\n"
+    "BM_string_memcmp/1024/0/0/iterations:1\n"
+    "BM_string_memcmp/8192/0/0/iterations:1\n"
+    "BM_string_memcmp/16384/0/0/iterations:1\n"
+    "BM_string_memcmp/32768/0/0/iterations:1\n"
+    "BM_string_memcmp/65536/0/0/iterations:1\n"
+    "BM_math_sqrt/iterations:1\n"
+    "BM_string_memcpy/512/4/4/iterations:25\n"
+    "BM_property_get/1/iterations:1\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_medium.xml",
+                                                "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, from_each) {
+  std::string expected =
+    "BM_empty/iterations:1\n"
+    "BM_math_sqrt/iterations:1\n"
+    "BM_property_get/1/iterations:1\n"
+    "BM_pthread_self/iterations:1\n"
+    "BM_semaphore_sem_getvalue/iterations:1\n"
+    "BM_stdio_fread/64/iterations:1\n"
+    "BM_string_memcpy/512/4/4/iterations:1\n"
+    "BM_time_clock_gettime/iterations:1\n"
+    "BM_unistd_getpid/iterations:1\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_from_each.xml",
+                                                "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, cmd_args) {
+  std::string expected =
+    "BM_string_memcpy/8/8/8/iterations:1\n"
+    "BM_math_log10/iterations:1\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_extra=BM_string_memcpy 8 8 8",
+                                                "--bionic_extra=BM_math_log10",
+                                                "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, cmd_args_no_iter) {
+  std::string expected =
+    "BM_string_memcpy/8/8/8\n"
+    "BM_math_log10\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_extra=BM_string_memcpy 8 8 8",
+                                                "--bionic_extra=BM_math_log10"});
+}
+
+TEST_F(SystemTests, xml_and_args) {
+  std::string expected =
+    "BM_string_memcmp/8/0/0/iterations:1\n"
+    "BM_string_memcmp/64/0/0/iterations:1\n"
+    "BM_string_memcmp/512/0/0/iterations:1\n"
+    "BM_string_memcmp/1024/0/0/iterations:1\n"
+    "BM_string_memcmp/8192/0/0/iterations:1\n"
+    "BM_string_memcmp/16384/0/0/iterations:1\n"
+    "BM_string_memcmp/32768/0/0/iterations:1\n"
+    "BM_string_memcmp/65536/0/0/iterations:1\n"
+    "BM_math_sqrt/iterations:1\n"
+    "BM_string_memcpy/512/4/4/iterations:25\n"
+    "BM_property_get/1/iterations:1\n"
+    "BM_string_memcpy/8/0/0/iterations:1\n"
+    "BM_string_memcpy/64/0/0/iterations:1\n"
+    "BM_string_memcpy/512/0/0/iterations:1\n"
+    "BM_string_memcpy/1024/0/0/iterations:1\n"
+    "BM_string_memcpy/8192/0/0/iterations:1\n"
+    "BM_string_memcpy/16384/0/0/iterations:1\n"
+    "BM_string_memcpy/32768/0/0/iterations:1\n"
+    "BM_string_memcpy/65536/0/0/iterations:1\n"
+    "BM_math_log10/iterations:1\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_extra=BM_string_memcpy AT_ALIGNED_TWOBUF",
+                                                "--bionic_extra=BM_math_log10",
+                                                "--bionic_cpu -1",
+                                                "--bionic_xml=suites/test_medium.xml",
+                                                "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, alignment) {
+  std::string expected =
+    "BM_string_memcmp/8/2/2/iterations:1\n"
+    "BM_string_memcmp/64/2/2/iterations:1\n"
+    "BM_string_memcmp/512/2/2/iterations:1\n"
+    "BM_string_memcmp/1024/2/2/iterations:1\n"
+    "BM_string_memcmp/8192/2/2/iterations:1\n"
+    "BM_string_memcmp/16384/2/2/iterations:1\n"
+    "BM_string_memcmp/32768/2/2/iterations:1\n"
+    "BM_string_memcmp/65536/2/2/iterations:1\n"
+    "BM_string_memcmp/8/4/4/iterations:1\n"
+    "BM_string_memcmp/64/4/4/iterations:1\n"
+    "BM_string_memcmp/512/4/4/iterations:1\n"
+    "BM_string_memcmp/1024/4/4/iterations:1\n"
+    "BM_string_memcmp/8192/4/4/iterations:1\n"
+    "BM_string_memcmp/16384/4/4/iterations:1\n"
+    "BM_string_memcmp/32768/4/4/iterations:1\n"
+    "BM_string_memcmp/65536/4/4/iterations:1\n"
+    "BM_string_memcmp/8/16/16/iterations:1\n"
+    "BM_string_memcmp/64/16/16/iterations:1\n"
+    "BM_string_memcmp/512/16/16/iterations:1\n"
+    "BM_string_memcmp/1024/16/16/iterations:1\n"
+    "BM_string_memcmp/8192/16/16/iterations:1\n"
+    "BM_string_memcmp/16384/16/16/iterations:1\n"
+    "BM_string_memcmp/32768/16/16/iterations:1\n"
+    "BM_string_memcmp/65536/16/16/iterations:1\n"
+    "BM_string_memcmp/8/512/512/iterations:1\n"
+    "BM_string_memcmp/64/512/512/iterations:1\n"
+    "BM_string_memcmp/512/512/512/iterations:1\n"
+    "BM_string_memcmp/1024/512/512/iterations:1\n"
+    "BM_string_memcmp/8192/512/512/iterations:1\n"
+    "BM_string_memcmp/16384/512/512/iterations:1\n"
+    "BM_string_memcmp/32768/512/512/iterations:1\n"
+    "BM_string_memcmp/65536/512/512/iterations:1\n"
+    "BM_string_memcmp/8/2048/2048/iterations:1\n"
+    "BM_string_memcmp/64/2048/2048/iterations:1\n"
+    "BM_string_memcmp/512/2048/2048/iterations:1\n"
+    "BM_string_memcmp/1024/2048/2048/iterations:1\n"
+    "BM_string_memcmp/8192/2048/2048/iterations:1\n"
+    "BM_string_memcmp/16384/2048/2048/iterations:1\n"
+    "BM_string_memcmp/32768/2048/2048/iterations:1\n"
+    "BM_string_memcmp/65536/2048/2048/iterations:1\n"
+    "BM_string_strlen/8/2/iterations:1\n"
+    "BM_string_strlen/64/2/iterations:1\n"
+    "BM_string_strlen/512/2/iterations:1\n"
+    "BM_string_strlen/1024/2/iterations:1\n"
+    "BM_string_strlen/8192/2/iterations:1\n"
+    "BM_string_strlen/16384/2/iterations:1\n"
+    "BM_string_strlen/32768/2/iterations:1\n"
+    "BM_string_strlen/65536/2/iterations:1\n"
+    "BM_string_strlen/8/4/iterations:1\n"
+    "BM_string_strlen/64/4/iterations:1\n"
+    "BM_string_strlen/512/4/iterations:1\n"
+    "BM_string_strlen/1024/4/iterations:1\n"
+    "BM_string_strlen/8192/4/iterations:1\n"
+    "BM_string_strlen/16384/4/iterations:1\n"
+    "BM_string_strlen/32768/4/iterations:1\n"
+    "BM_string_strlen/65536/4/iterations:1\n"
+    "BM_string_strlen/8/16/iterations:1\n"
+    "BM_string_strlen/64/16/iterations:1\n"
+    "BM_string_strlen/512/16/iterations:1\n"
+    "BM_string_strlen/1024/16/iterations:1\n"
+    "BM_string_strlen/8192/16/iterations:1\n"
+    "BM_string_strlen/16384/16/iterations:1\n"
+    "BM_string_strlen/32768/16/iterations:1\n"
+    "BM_string_strlen/65536/16/iterations:1\n"
+    "BM_string_strlen/8/512/iterations:1\n"
+    "BM_string_strlen/64/512/iterations:1\n"
+    "BM_string_strlen/512/512/iterations:1\n"
+    "BM_string_strlen/1024/512/iterations:1\n"
+    "BM_string_strlen/8192/512/iterations:1\n"
+    "BM_string_strlen/16384/512/iterations:1\n"
+    "BM_string_strlen/32768/512/iterations:1\n"
+    "BM_string_strlen/65536/512/iterations:1\n"
+    "BM_string_strlen/8/2048/iterations:1\n"
+    "BM_string_strlen/64/2048/iterations:1\n"
+    "BM_string_strlen/512/2048/iterations:1\n"
+    "BM_string_strlen/1024/2048/iterations:1\n"
+    "BM_string_strlen/8192/2048/iterations:1\n"
+    "BM_string_strlen/16384/2048/iterations:1\n"
+    "BM_string_strlen/32768/2048/iterations:1\n"
+    "BM_string_strlen/65536/2048/iterations:1\n";
+  Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_alignment.xml",
+                                                "--bionic_iterations=100"});
+}
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index c90dfad..4c6d5dd 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -20,6 +20,7 @@
 #include <unistd.h>
 
 #include <benchmark/benchmark.h>
+#include "util.h"
 
 static void BM_time_clock_gettime(benchmark::State& state) {
   timespec t;
@@ -27,7 +28,7 @@
     clock_gettime(CLOCK_MONOTONIC, &t);
   }
 }
-BENCHMARK(BM_time_clock_gettime);
+BIONIC_BENCHMARK(BM_time_clock_gettime);
 
 static void BM_time_clock_gettime_syscall(benchmark::State& state) {
   timespec t;
@@ -35,7 +36,7 @@
     syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
   }
 }
-BENCHMARK(BM_time_clock_gettime_syscall);
+BIONIC_BENCHMARK(BM_time_clock_gettime_syscall);
 
 static void BM_time_gettimeofday(benchmark::State& state) {
   timeval tv;
@@ -43,7 +44,7 @@
     gettimeofday(&tv, nullptr);
   }
 }
-BENCHMARK(BM_time_gettimeofday);
+BIONIC_BENCHMARK(BM_time_gettimeofday);
 
 void BM_time_gettimeofday_syscall(benchmark::State& state) {
   timeval tv;
@@ -51,14 +52,14 @@
     syscall(__NR_gettimeofday, &tv, nullptr);
   }
 }
-BENCHMARK(BM_time_gettimeofday_syscall);
+BIONIC_BENCHMARK(BM_time_gettimeofday_syscall);
 
 void BM_time_time(benchmark::State& state) {
   while (state.KeepRunning()) {
     time(nullptr);
   }
 }
-BENCHMARK(BM_time_time);
+BIONIC_BENCHMARK(BM_time_time);
 
 void BM_time_localtime(benchmark::State& state) {
   time_t t = time(nullptr);
@@ -66,7 +67,7 @@
     localtime(&t);
   }
 }
-BENCHMARK(BM_time_localtime);
+BIONIC_BENCHMARK(BM_time_localtime);
 
 void BM_time_localtime_r(benchmark::State& state) {
   time_t t = time(nullptr);
@@ -75,4 +76,4 @@
     localtime_r(&t, &tm);
   }
 }
-BENCHMARK(BM_time_localtime_r);
+BIONIC_BENCHMARK(BM_time_localtime_r);
diff --git a/benchmarks/unistd_benchmark.cpp b/benchmarks/unistd_benchmark.cpp
index b78d3eb..98e8858 100644
--- a/benchmarks/unistd_benchmark.cpp
+++ b/benchmarks/unistd_benchmark.cpp
@@ -18,20 +18,21 @@
 #include <unistd.h>
 
 #include <benchmark/benchmark.h>
+#include "util.h"
 
 static void BM_unistd_getpid(benchmark::State& state) {
   while (state.KeepRunning()) {
     getpid();
   }
 }
-BENCHMARK(BM_unistd_getpid);
+BIONIC_BENCHMARK(BM_unistd_getpid);
 
 static void BM_unistd_getpid_syscall(benchmark::State& state) {
   while (state.KeepRunning()) {
     syscall(__NR_getpid);
   }
 }
-BENCHMARK(BM_unistd_getpid_syscall);
+BIONIC_BENCHMARK(BM_unistd_getpid_syscall);
 
 #if defined(__BIONIC__)
 
@@ -43,7 +44,7 @@
     gettid_fp();
   }
 }
-BENCHMARK(BM_unistd_gettid);
+BIONIC_BENCHMARK(BM_unistd_gettid);
 
 #endif
 
@@ -52,6 +53,4 @@
     syscall(__NR_gettid);
   }
 }
-BENCHMARK(BM_unistd_gettid_syscall);
-
-BENCHMARK_MAIN()
+BIONIC_BENCHMARK(BM_unistd_gettid_syscall);
diff --git a/benchmarks/util.cpp b/benchmarks/util.cpp
index d9641cf..92e8243 100644
--- a/benchmarks/util.cpp
+++ b/benchmarks/util.cpp
@@ -16,21 +16,22 @@
 
 #include "util.h"
 
+#include <err.h>
+#include <math.h>
 #include <sched.h>
 #include <stdio.h>
 #include <string.h>
+#include <wchar.h>
+
 #include <cstdlib>
-#include <vector>
 
 // This function returns a pointer less than 2 * alignment + or_mask bytes into the array.
-char *GetAlignedMemory(char *orig_ptr, size_t alignment, size_t or_mask) {
+char* GetAlignedMemory(char* orig_ptr, size_t alignment, size_t or_mask) {
   if ((alignment & (alignment - 1)) != 0) {
-    fprintf(stderr, "warning: alignment passed into GetAlignedMemory is not a power of two.\n");
-    std::abort();
+    errx(1, "warning: alignment passed into GetAlignedMemory is not a power of two.");
   }
   if (or_mask > alignment) {
-    fprintf(stderr, "warning: or_mask passed into GetAlignedMemory is too high.\n");
-    std::abort();
+    errx(1, "warning: or_mask passed into GetAlignedMemory is too high.");
   }
   uintptr_t ptr = reinterpret_cast<uintptr_t>(orig_ptr);
   if (alignment > 0) {
@@ -44,12 +45,18 @@
   return reinterpret_cast<char*>(ptr);
 }
 
-char *GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes) {
+char* GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes) {
   buf->resize(nbytes + 3 * alignment);
   return GetAlignedMemory(buf->data(), alignment, 0);
 }
 
-char *GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte) {
+wchar_t* GetAlignedPtr(std::vector<wchar_t>* buf, size_t alignment, size_t nchars) {
+  buf->resize(nchars + ceil((3 * alignment) / sizeof(wchar_t)));
+  return reinterpret_cast<wchar_t*>(GetAlignedMemory(reinterpret_cast<char*>(buf->data()),
+                                                     alignment, 0));
+}
+
+char* GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte) {
   char* buf_aligned = GetAlignedPtr(buf, alignment, nbytes);
   memset(buf_aligned, fill_byte, nbytes);
   return buf_aligned;
@@ -64,7 +71,7 @@
 
 #else
 
-bool LockToCPU(int cpu_to_lock) {
+bool LockToCPU(long cpu_to_lock) {
   cpu_set_t cpuset;
 
   CPU_ZERO(&cpuset);
@@ -81,7 +88,7 @@
       }
     }
   } else if (!CPU_ISSET(cpu_to_lock, &cpuset)) {
-    printf("Cpu %d does not exist.\n", cpu_to_lock);
+    printf("Cpu %ld does not exist.\n", cpu_to_lock);
     return false;
   }
 
diff --git a/benchmarks/util.h b/benchmarks/util.h
index bd3d515..cf6f50e 100644
--- a/benchmarks/util.h
+++ b/benchmarks/util.h
@@ -17,15 +17,45 @@
 #ifndef _BIONIC_BENCHMARKS_UTIL_H_
 #define _BIONIC_BENCHMARKS_UTIL_H_
 
+#include <map>
+#include <mutex>
+#include <string>
 #include <vector>
 
+typedef void (*benchmark_func_t) (void);
+
+extern std::mutex g_map_lock;
+
+extern std::map<std::string, benchmark_func_t> g_str_to_func;
+
+static int  __attribute__((unused)) EmplaceBenchmark (std::string fn_name, benchmark_func_t fn_ptr) {
+  g_map_lock.lock();
+  g_str_to_func.emplace(std::string(fn_name), fn_ptr);
+  g_map_lock.unlock();
+  return 0;
+}
+
+#define BIONIC_BENCHMARK(n) \
+  int _bionic_benchmark_##n __attribute__((unused)) = EmplaceBenchmark(std::string(#n), reinterpret_cast<benchmark_func_t>(n))
+
+constexpr auto KB = 1024;
+
+typedef struct {
+  long cpu_to_lock;
+  long num_iterations;
+  std::string xmlpath;
+  std::vector<std::string> extra_benchmarks;
+} bench_opts_t;
+
 // This function returns a pointer less than 2 * alignment + or_mask bytes into the array.
-char *GetAlignedMemory(char *orig_ptr, size_t alignment, size_t or_mask);
+char* GetAlignedMemory(char* orig_ptr, size_t alignment, size_t or_mask);
 
-char *GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes);
+char* GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes);
 
-char *GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte);
+wchar_t* GetAlignedPtr(std::vector<wchar_t>* buf, size_t alignment, size_t nbytes);
 
-bool LockToCPU(int cpu_to_lock);
+char* GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte);
+
+bool LockToCPU(long cpu_to_lock);
 
 #endif // _BIONIC_BENCHMARKS_UTIL_H
diff --git a/libc/bionic/open.cpp b/libc/bionic/open.cpp
index 6d179c4..222e5d3 100644
--- a/libc/bionic/open.cpp
+++ b/libc/bionic/open.cpp
@@ -43,6 +43,10 @@
 #endif
 }
 
+static inline bool needs_mode(int flags) {
+  return ((flags & O_CREAT) == O_CREAT) || ((flags & O_TMPFILE) == O_TMPFILE);
+}
+
 int creat(const char* pathname, mode_t mode) {
   return open(pathname, O_CREAT | O_TRUNC | O_WRONLY, mode);
 }
@@ -51,7 +55,7 @@
 int open(const char* pathname, int flags, ...) {
   mode_t mode = 0;
 
-  if ((flags & O_CREAT) != 0) {
+  if (needs_mode(flags)) {
     va_list args;
     va_start(args, flags);
     mode = static_cast<mode_t>(va_arg(args, int));
@@ -63,17 +67,14 @@
 __strong_alias(open64, open);
 
 int __open_2(const char* pathname, int flags) {
-  if (__predict_false((flags & O_CREAT) != 0)) {
-    __fortify_fatal("open(O_CREAT): called without specifying a mode");
-  }
-
+  if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
   return __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0);
 }
 
 int openat(int fd, const char *pathname, int flags, ...) {
   mode_t mode = 0;
 
-  if ((flags & O_CREAT) != 0) {
+  if (needs_mode(flags)) {
     va_list args;
     va_start(args, flags);
     mode = static_cast<mode_t>(va_arg(args, int));
@@ -85,9 +86,6 @@
 __strong_alias(openat64, openat);
 
 int __openat_2(int fd, const char* pathname, int flags) {
-  if ((flags & O_CREAT) != 0) {
-    __fortify_fatal("openat(O_CREAT): called without specifying a mode");
-  }
-
+  if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
   return __openat(fd, pathname, force_O_LARGEFILE(flags), 0);
 }
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 9197aa3..9be86f1 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -278,7 +278,7 @@
       munmap(thread->attr.stack_base, thread->mmap_size);
     }
     async_safe_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: clone failed: %s",
-                          strerror(errno));
+                          strerror(clone_errno));
     return clone_errno;
   }
 
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index ca3bd25..c824544 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -129,7 +129,7 @@
   struct android_namespace_t* library_namespace;
 } android_dlextinfo;
 
-void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo)
+void* android_dlopen_ext(const char* __filename, int __flags, const android_dlextinfo* __info)
   __INTRODUCED_IN(21);
 
 __END_DECLS
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index 09db2a6..4d474b0 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -39,7 +39,7 @@
 
 #if __ANDROID_API__ < __ANDROID_API_L__
 
-sighandler_t bsd_signal(int signum, sighandler_t handler) __REMOVED_IN(21);
+sighandler_t bsd_signal(int __signal, sighandler_t __handler) __REMOVED_IN(21);
 
 /* These weren't introduced until L. */
 int __libc_current_sigrtmax() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index e26e5f2..0d6f2c2 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -38,6 +38,8 @@
 
 __BEGIN_DECLS
 
+__noreturn void _Exit(int) __RENAME(_exit);
+
 static __inline float strtof(const char* nptr, char** endptr) {
   double d = strtod(nptr, endptr);
   if (d > FLT_MAX) {
diff --git a/libc/include/android/legacy_sys_stat_inlines.h b/libc/include/android/legacy_sys_stat_inlines.h
index 23a9f07..bbf54c0 100644
--- a/libc/include/android/legacy_sys_stat_inlines.h
+++ b/libc/include/android/legacy_sys_stat_inlines.h
@@ -36,8 +36,8 @@
 
 __BEGIN_DECLS
 
-static __inline int mkfifo(const char *__p, mode_t __m) {
-  return mknod(__p, (__m & ~S_IFMT) | S_IFIFO, (dev_t)0);
+static __inline int mkfifo(const char* __path, mode_t __mode) {
+  return mknod(__path, (__mode & ~S_IFMT) | S_IFIFO, (dev_t)0);
 }
 
 __END_DECLS
diff --git a/libc/include/android/set_abort_message.h b/libc/include/android/set_abort_message.h
index 18881a3..3dde673 100644
--- a/libc/include/android/set_abort_message.h
+++ b/libc/include/android/set_abort_message.h
@@ -33,7 +33,7 @@
 
 __BEGIN_DECLS
 
-void android_set_abort_message(const char* msg) __INTRODUCED_IN(21);
+void android_set_abort_message(const char* __msg) __INTRODUCED_IN(21);
 
 __END_DECLS
 
diff --git a/libc/include/bits/fcntl.h b/libc/include/bits/fcntl.h
index 604d35a..e3b0e8c 100644
--- a/libc/include/bits/fcntl.h
+++ b/libc/include/bits/fcntl.h
@@ -33,7 +33,7 @@
 
 __BEGIN_DECLS
 
-int fcntl(int, int, ...);
+int fcntl(int __fd, int __cmd, ...);
 
 __END_DECLS
 
diff --git a/libc/include/bits/fortify/fcntl.h b/libc/include/bits/fortify/fcntl.h
index 3e0a590..6d90341 100644
--- a/libc/include/bits/fortify/fcntl.h
+++ b/libc/include/bits/fortify/fcntl.h
@@ -40,7 +40,10 @@
 
 #if defined(__BIONIC_FORTIFY)
 #define __open_too_many_args_error "too many arguments"
-#define __open_too_few_args_error "called with O_CREAT, but missing mode"
+#define __open_too_few_args_error "called with O_CREAT or O_TMPFILE, but missing mode"
+#define __open_useless_modes_warning "has superfluous mode bits; missing O_CREAT?"
+/* O_TMPFILE shares bits with O_DIRECTORY. */
+#define __open_modes_useful(flags) (((flags) & O_CREAT) || ((flags) & O_TMPFILE) == O_TMPFILE)
 #if defined(__clang__)
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
@@ -57,12 +60,15 @@
 __BIONIC_FORTIFY_INLINE
 int open(const char* const __pass_object_size pathname, int flags)
         __overloadable
-        __clang_error_if(flags & O_CREAT, "'open' " __open_too_few_args_error) {
+        __clang_error_if(__open_modes_useful(flags), "'open' " __open_too_few_args_error) {
     return __open_2(pathname, flags);
 }
 
 __BIONIC_FORTIFY_INLINE
-int open(const char* const __pass_object_size pathname, int flags, mode_t modes) __overloadable {
+int open(const char* const __pass_object_size pathname, int flags, mode_t modes)
+        __overloadable
+        __clang_warning_if(!__open_modes_useful(flags) && modes,
+                           "'open' " __open_useless_modes_warning) {
     return __open_real(pathname, flags, modes);
 }
 
@@ -72,16 +78,17 @@
         __errorattr(__open_too_many_args_error);
 
 __BIONIC_FORTIFY_INLINE
-int openat(int dirfd, const char* const __pass_object_size pathname,
-           int flags)
+int openat(int dirfd, const char* const __pass_object_size pathname, int flags)
         __overloadable
-        __clang_error_if(flags & O_CREAT, "'openat' " __open_too_few_args_error) {
+        __clang_error_if(__open_modes_useful(flags), "'openat' " __open_too_few_args_error) {
     return __openat_2(dirfd, pathname, flags);
 }
 
 __BIONIC_FORTIFY_INLINE
-int openat(int dirfd, const char* const __pass_object_size pathname, int flags,
-           mode_t modes) __overloadable {
+int openat(int dirfd, const char* const __pass_object_size pathname, int flags, mode_t modes)
+        __overloadable
+        __clang_warning_if(!__open_modes_useful(flags) && modes,
+                           "'openat' " __open_useless_modes_warning) {
     return __openat_real(dirfd, pathname, flags, modes);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
@@ -94,7 +101,7 @@
 __BIONIC_FORTIFY_INLINE
 int open(const char* pathname, int flags, ...) {
     if (__builtin_constant_p(flags)) {
-        if ((flags & O_CREAT) && __builtin_va_arg_pack_len() == 0) {
+        if (__open_modes_useful(flags) && __builtin_va_arg_pack_len() == 0) {
             __creat_missing_mode();  /* Compile time error. */
         }
     }
@@ -113,7 +120,7 @@
 __BIONIC_FORTIFY_INLINE
 int openat(int dirfd, const char* pathname, int flags, ...) {
     if (__builtin_constant_p(flags)) {
-        if ((flags & O_CREAT) && __builtin_va_arg_pack_len() == 0) {
+        if (__open_modes_useful(flags) && __builtin_va_arg_pack_len() == 0) {
             __creat_missing_mode();  /* Compile time error. */
         }
     }
@@ -134,4 +141,6 @@
 
 #undef __open_too_many_args_error
 #undef __open_too_few_args_error
+#undef __open_useless_modes_warning
+#undef __open_modes_useful
 #endif /* defined(__BIONIC_FORTIFY) */
diff --git a/libc/include/bits/fortify/stdlib.h b/libc/include/bits/fortify/stdlib.h
index cf4b7ea..8f3b02c 100644
--- a/libc/include/bits/fortify/stdlib.h
+++ b/libc/include/bits/fortify/stdlib.h
@@ -40,7 +40,8 @@
 #if defined(__clang__)
 char* realpath(const char* path, char* resolved)
         __clang_error_if(__bos(resolved) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
-                         __bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str);
+                         __bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str)
+        __clang_error_if(!path, "'realpath': NULL path is never correct; flipped arguments?");
 /* No need for a definition; the only issues we can catch are at compile-time. */
 
 #else /* defined(__clang__) */
diff --git a/libc/include/bits/getopt.h b/libc/include/bits/getopt.h
index 7153d48..5481449 100644
--- a/libc/include/bits/getopt.h
+++ b/libc/include/bits/getopt.h
@@ -33,9 +33,9 @@
 
 __BEGIN_DECLS
 
-int	 getopt(int, char * const [], const char *);
+int getopt(int __argc, char* const __argv[], const char* __options);
 
-extern char *optarg;			/* getopt(3) external variables */
+extern char* optarg;
 extern int optind, opterr, optopt;
 
 __END_DECLS
diff --git a/libc/include/bits/glibc-syscalls.h b/libc/include/bits/glibc-syscalls.h
index 3f99dcb..f08c614 100644
--- a/libc/include/bits/glibc-syscalls.h
+++ b/libc/include/bits/glibc-syscalls.h
@@ -1,6 +1,15 @@
 /* Generated by gensyscalls.py. Do not edit. */
 #ifndef _BIONIC_BITS_GLIBC_SYSCALLS_H_
 #define _BIONIC_BITS_GLIBC_SYSCALLS_H_
+#if defined(__NR__llseek)
+  #define SYS__llseek __NR__llseek
+#endif
+#if defined(__NR__newselect)
+  #define SYS__newselect __NR__newselect
+#endif
+#if defined(__NR__sysctl)
+  #define SYS__sysctl __NR__sysctl
+#endif
 #if defined(__NR_accept)
   #define SYS_accept __NR_accept
 #endif
diff --git a/libc/include/bits/ioctl.h b/libc/include/bits/ioctl.h
index 53116ca..0cf87d2 100644
--- a/libc/include/bits/ioctl.h
+++ b/libc/include/bits/ioctl.h
@@ -33,7 +33,7 @@
 
 __BEGIN_DECLS
 
-int ioctl(int, int, ...);
+int ioctl(int __fd, int __request, ...);
 
 __END_DECLS
 
diff --git a/libc/include/bits/lockf.h b/libc/include/bits/lockf.h
index a8e273e..929c68c 100644
--- a/libc/include/bits/lockf.h
+++ b/libc/include/bits/lockf.h
@@ -39,8 +39,8 @@
 
 __BEGIN_DECLS
 
-int lockf(int, int, off_t) __RENAME_IF_FILE_OFFSET64(lockf64) __INTRODUCED_IN(24);
-int lockf64(int, int, off64_t) __INTRODUCED_IN(24);
+int lockf(int __fd, int __cmd, off_t __length) __RENAME_IF_FILE_OFFSET64(lockf64) __INTRODUCED_IN(24);
+int lockf64(int __fd, int __cmd, off64_t __length) __INTRODUCED_IN(24);
 
 __END_DECLS
 
diff --git a/libc/include/bits/strcasecmp.h b/libc/include/bits/strcasecmp.h
index df1a6b8..594046a 100644
--- a/libc/include/bits/strcasecmp.h
+++ b/libc/include/bits/strcasecmp.h
@@ -35,10 +35,10 @@
 
 __BEGIN_DECLS
 
-int strcasecmp(const char*, const char*) __attribute_pure__;
-int strcasecmp_l(const char*, const char*, locale_t) __attribute_pure__ __INTRODUCED_IN(23);
-int strncasecmp(const char*, const char*, size_t) __attribute_pure__;
-int strncasecmp_l(const char*, const char*, size_t, locale_t) __attribute_pure__ __INTRODUCED_IN(23);
+int strcasecmp(const char* __s1, const char* __s2) __attribute_pure__;
+int strcasecmp_l(const char* __s1, const char* __s2, locale_t __l) __attribute_pure__ __INTRODUCED_IN(23);
+int strncasecmp(const char* __s1, const char* __s2, size_t __n) __attribute_pure__;
+int strncasecmp_l(const char* __s1, const char* __s2, size_t __n, locale_t __l) __attribute_pure__ __INTRODUCED_IN(23);
 
 __END_DECLS
 
diff --git a/libc/include/bits/wctype.h b/libc/include/bits/wctype.h
index f21d46e..a51eca2 100644
--- a/libc/include/bits/wctype.h
+++ b/libc/include/bits/wctype.h
@@ -37,29 +37,29 @@
 
 #define WEOF __BIONIC_CAST(static_cast, wint_t, -1)
 
-int iswalnum(wint_t);
-int iswalpha(wint_t);
-int iswblank(wint_t) __INTRODUCED_IN(21);
-int iswcntrl(wint_t);
-int iswdigit(wint_t);
-int iswgraph(wint_t);
-int iswlower(wint_t);
-int iswprint(wint_t);
-int iswpunct(wint_t);
-int iswspace(wint_t);
-int iswupper(wint_t);
-int iswxdigit(wint_t);
+int iswalnum(wint_t __wc);
+int iswalpha(wint_t __wc);
+int iswblank(wint_t __wc) __INTRODUCED_IN(21);
+int iswcntrl(wint_t __wc);
+int iswdigit(wint_t __wc);
+int iswgraph(wint_t __wc);
+int iswlower(wint_t __wc);
+int iswprint(wint_t __wc);
+int iswpunct(wint_t __wc);
+int iswspace(wint_t __wc);
+int iswupper(wint_t __wc);
+int iswxdigit(wint_t __wc);
 
-wint_t towlower(wint_t);
-wint_t towupper(wint_t);
+wint_t towlower(wint_t __wc);
+wint_t towupper(wint_t __wc);
 
 typedef long wctype_t;
-wctype_t wctype(const char*);
-int iswctype(wint_t, wctype_t);
+wctype_t wctype(const char* __name);
+int iswctype(wint_t __wc, wctype_t __type);
 
 typedef const void* wctrans_t;
-wint_t towctrans(wint_t, wctrans_t) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
-wctrans_t wctrans(const char*) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
+wint_t towctrans(wint_t __wc, wctrans_t __transform) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
+wctrans_t wctrans(const char* __name) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
 
 __END_DECLS
 
diff --git a/libc/include/fts.h b/libc/include/fts.h
index b46c19c..3649d3a 100644
--- a/libc/include/fts.h
+++ b/libc/include/fts.h
@@ -115,12 +115,13 @@
 } FTSENT;
 
 __BEGIN_DECLS
-FTSENT	*fts_children(FTS *, int);
-int	 fts_close(FTS *);
-FTS	*fts_open(char * const *, int,
-	    int (*)(const FTSENT **, const FTSENT **));
-FTSENT	*fts_read(FTS *);
-int	 fts_set(FTS *, FTSENT *, int);
+
+FTSENT* fts_children(FTS* __fts, int __options);
+int fts_close(FTS* __fts);
+FTS* fts_open(char* const* __path, int __options, int (*__comparator)(const FTSENT** __lhs, const FTSENT** __rhs));
+FTSENT* fts_read(FTS* __fts);
+int fts_set(FTS* __fts, FTSENT* __entry, int __options);
+
 __END_DECLS
 
 #endif /* !_FTS_H_ */
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index db5da04..80b08f6 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -30,13 +30,13 @@
 #define __BIONIC_ALLOC_SIZE(...) __attribute__((__alloc_size__(__VA_ARGS__)))
 #endif
 
-void* malloc(size_t byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
-void* calloc(size_t item_count, size_t item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
-void* realloc(void* p, size_t byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
-void free(void* p);
+void* malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
+void* calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
+void* realloc(void* __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
+void free(void* __ptr);
 
-void* memalign(size_t alignment, size_t byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
-size_t malloc_usable_size(const void* p) __INTRODUCED_IN(17);
+void* memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
+size_t malloc_usable_size(const void* __ptr) __INTRODUCED_IN(17);
 
 #ifndef STRUCT_MALLINFO_DECLARED
 #define STRUCT_MALLINFO_DECLARED 1
@@ -75,12 +75,11 @@
  *   <!-- more heaps -->
  * </malloc>
  */
-int malloc_info(int, FILE*) __INTRODUCED_IN(23);
+int malloc_info(int __must_be_zero, FILE* __fp) __INTRODUCED_IN(23);
 
 /* mallopt options */
 #define M_DECAY_TIME -100
-
-int mallopt(int, int) __INTRODUCED_IN(26);
+int mallopt(int __option, int __value) __INTRODUCED_IN(26);
 
 __END_DECLS
 
diff --git a/libc/include/netinet/ether.h b/libc/include/netinet/ether.h
index e69cdaf..3e6a4e3 100644
--- a/libc/include/netinet/ether.h
+++ b/libc/include/netinet/ether.h
@@ -34,10 +34,10 @@
 
 __BEGIN_DECLS
 
-char* ether_ntoa(const struct ether_addr*) __INTRODUCED_IN(11);
-char* ether_ntoa_r(const struct ether_addr*, char*) __INTRODUCED_IN(11);
-struct ether_addr* ether_aton(const char*) __INTRODUCED_IN(11);
-struct ether_addr* ether_aton_r(const char*, struct ether_addr*) __INTRODUCED_IN(11);
+char* ether_ntoa(const struct ether_addr* __addr) __INTRODUCED_IN(11);
+char* ether_ntoa_r(const struct ether_addr* __addr, char* __buf) __INTRODUCED_IN(11);
+struct ether_addr* ether_aton(const char* __ascii) __INTRODUCED_IN(11);
+struct ether_addr* ether_aton_r(const char* __ascii, struct ether_addr* __addr) __INTRODUCED_IN(11);
 
 __END_DECLS
 
diff --git a/libc/include/netinet/in.h b/libc/include/netinet/in.h
index 10fbafa..0ca8c82 100644
--- a/libc/include/netinet/in.h
+++ b/libc/include/netinet/in.h
@@ -45,7 +45,7 @@
 typedef uint16_t in_port_t;
 typedef uint32_t in_addr_t;
 
-int bindresvport(int, struct sockaddr_in*);
+int bindresvport(int __fd, struct sockaddr_in* __sin);
 
 #if __ANDROID_API__ >= __ANDROID_API_N__
 extern const struct in6_addr in6addr_any __INTRODUCED_IN(24);
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 7165738..ccafd78 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -152,7 +152,7 @@
 int pthread_mutex_trylock(pthread_mutex_t*);
 int pthread_mutex_unlock(pthread_mutex_t*);
 
-#if defined(__LP32__) && __ANDROID_API__ < 21
+#if __ANDROID_API__ < 21
 /*
  * Cruft for supporting old API levels. Pre-L we didn't have the proper POSIX
  * APIs for things, but instead had some locally grown, artisan equivalents.
@@ -164,7 +164,6 @@
  *  * https://github.com/android-ndk/ndk/issues/423
  *  * https://stackoverflow.com/q/44580542/632035
  */
-
 int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex, unsigned msecs);
 int pthread_cond_timeout_np(pthread_cond_t* cond, pthread_mutex_t* mutex, unsigned msecs);
 int pthread_cond_timedwait_monotonic_np(pthread_cond_t*, pthread_mutex_t*, const struct timespec*);
diff --git a/libc/include/sched.h b/libc/include/sched.h
index b8ef44b..de6969f8 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -42,22 +42,22 @@
   int sched_priority;
 };
 
-int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param);
-int sched_getscheduler(pid_t pid);
+int sched_setscheduler(pid_t __pid, int __policy, const struct sched_param* __param);
+int sched_getscheduler(pid_t __pid);
 int sched_yield(void);
-int sched_get_priority_max(int policy);
-int sched_get_priority_min(int policy);
-int sched_setparam(pid_t pid, const struct sched_param* param);
-int sched_getparam(pid_t pid, struct sched_param* param);
-int sched_rr_get_interval(pid_t pid, struct timespec* quantum);
+int sched_get_priority_max(int __policy);
+int sched_get_priority_min(int __policy);
+int sched_setparam(pid_t __pid, const struct sched_param* __param);
+int sched_getparam(pid_t __pid, struct sched_param* __param);
+int sched_rr_get_interval(pid_t __pid, struct timespec* __quantum);
 
 #if defined(__USE_GNU)
 
-int clone(int (*fn)(void*), void* child_stack, int flags, void* arg, ...)
+int clone(int (*__fn)(void*), void* __child_stack, int __flags, void* __arg, ...)
     __INTRODUCED_IN_ARM(9) __INTRODUCED_IN_MIPS(12) __INTRODUCED_IN_X86(17);
-int unshare(int flags) __INTRODUCED_IN(17);
+int unshare(int __flags) __INTRODUCED_IN(17);
 int sched_getcpu(void) __INTRODUCED_IN(12);
-int setns(int fd, int ns_type) __INTRODUCED_IN(21);
+int setns(int __fd, int __ns_type) __INTRODUCED_IN(21);
 
 #ifdef __LP64__
 #define CPU_SETSIZE 1024
@@ -74,8 +74,8 @@
   __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
 } cpu_set_t;
 
-int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) __INTRODUCED_IN(12);
-int sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set) __INTRODUCED_IN(12);
+int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* __set) __INTRODUCED_IN(12);
+int sched_getaffinity(pid_t __pid, size_t __set_size, cpu_set_t* __set) __INTRODUCED_IN(12);
 
 #define CPU_ZERO(set)          CPU_ZERO_S(sizeof(cpu_set_t), set)
 #define CPU_SET(cpu, set)      CPU_SET_S(cpu, sizeof(cpu_set_t), set)
@@ -98,8 +98,8 @@
 #define CPU_ALLOC(count)  __sched_cpualloc((count))
 #define CPU_FREE(set)     __sched_cpufree((set))
 
-cpu_set_t* __sched_cpualloc(size_t count) __INTRODUCED_IN(12);
-void __sched_cpufree(cpu_set_t* set) __INTRODUCED_IN(12);
+cpu_set_t* __sched_cpualloc(size_t __count) __INTRODUCED_IN(12);
+void __sched_cpufree(cpu_set_t* __set) __INTRODUCED_IN(12);
 
 #define CPU_ZERO_S(setsize, set)  __builtin_memset(set, 0, setsize)
 
@@ -143,7 +143,7 @@
 
 #define CPU_COUNT_S(setsize, set)  __sched_cpucount((setsize), (set))
 
-int __sched_cpucount(size_t setsize, cpu_set_t* set) __INTRODUCED_IN(12);
+int __sched_cpucount(size_t __set_size, cpu_set_t* __set) __INTRODUCED_IN(12);
 
 #endif /* __USE_GNU */
 
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 89d85fc..ece2916 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -109,55 +109,55 @@
 
 #endif
 
-int sigaction(int, const struct sigaction*, struct sigaction*);
+int sigaction(int __signal, const struct sigaction* __new_action, struct sigaction* __old_action);
 
-int siginterrupt(int, int);
+int siginterrupt(int __signal, int __flag);
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
-sighandler_t signal(int, sighandler_t) __INTRODUCED_IN(21);
-int sigaddset(sigset_t*, int) __INTRODUCED_IN(21);
-int sigdelset(sigset_t*, int) __INTRODUCED_IN(21);
-int sigemptyset(sigset_t*) __INTRODUCED_IN(21);
-int sigfillset(sigset_t*) __INTRODUCED_IN(21);
-int sigismember(const sigset_t*, int) __INTRODUCED_IN(21);
+sighandler_t signal(int __signal, sighandler_t __handler) __INTRODUCED_IN(21);
+int sigaddset(sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigdelset(sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigemptyset(sigset_t* __set) __INTRODUCED_IN(21);
+int sigfillset(sigset_t* __set) __INTRODUCED_IN(21);
+int sigismember(const sigset_t* __set, int __signal) __INTRODUCED_IN(21);
 #else
 // Implemented as static inlines before 21.
 #endif
 
-int sigpending(sigset_t*);
-int sigprocmask(int, const sigset_t*, sigset_t*);
-int sigsuspend(const sigset_t*);
-int sigwait(const sigset_t*, int*);
+int sigpending(sigset_t* __set);
+int sigprocmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
+int sigsuspend(const sigset_t* __mask);
+int sigwait(const sigset_t* __set, int* __signal);
 
-int sighold(int)
+int sighold(int __signal)
   __attribute__((deprecated("use sigprocmask() or pthread_sigmask() instead")))
   __INTRODUCED_IN(26);
-int sigignore(int)
+int sigignore(int __signal)
   __attribute__((deprecated("use sigaction() instead"))) __INTRODUCED_IN(26);
-int sigpause(int)
+int sigpause(int __signal)
   __attribute__((deprecated("use sigsuspend() instead"))) __INTRODUCED_IN(26);
-int sigrelse(int)
+int sigrelse(int __signal)
   __attribute__((deprecated("use sigprocmask() or pthread_sigmask() instead")))
   __INTRODUCED_IN(26);
-sighandler_t sigset(int, sighandler_t)
+sighandler_t sigset(int __signal, sighandler_t __handler)
   __attribute__((deprecated("use sigaction() instead"))) __INTRODUCED_IN(26);
 
-int raise(int);
-int kill(pid_t, int);
-int killpg(int, int);
-int tgkill(int tgid, int tid, int sig) __INTRODUCED_IN_32(16);
+int raise(int __signal);
+int kill(pid_t __pid, int __signal);
+int killpg(int __pgrp, int __signal);
+int tgkill(int __tgid, int __tid, int __signal) __INTRODUCED_IN_32(16);
 
-int sigaltstack(const stack_t*, stack_t*);
+int sigaltstack(const stack_t* __new_signal_stack, stack_t* __old_signal_stack);
 
-void psiginfo(const siginfo_t*, const char*) __INTRODUCED_IN(17);
-void psignal(int, const char*) __INTRODUCED_IN(17);
+void psiginfo(const siginfo_t* __info, const char* __msg) __INTRODUCED_IN(17);
+void psignal(int __signal, const char* __msg) __INTRODUCED_IN(17);
 
-int pthread_kill(pthread_t, int);
-int pthread_sigmask(int, const sigset_t*, sigset_t*);
+int pthread_kill(pthread_t __pthread, int __signal);
+int pthread_sigmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
 
-int sigqueue(pid_t, int, const union sigval) __INTRODUCED_IN(23);
-int sigtimedwait(const sigset_t*, siginfo_t*, const struct timespec*) __INTRODUCED_IN(23);
-int sigwaitinfo(const sigset_t*, siginfo_t*) __INTRODUCED_IN(23);
+int sigqueue(pid_t __pid, int __signal, const union sigval __value) __INTRODUCED_IN(23);
+int sigtimedwait(const sigset_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(23);
+int sigwaitinfo(const sigset_t* __set, siginfo_t* __info) __INTRODUCED_IN(23);
 
 __END_DECLS
 
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 7e5a976..4dff48d 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -153,8 +153,8 @@
  * Allow users to just use dprintf and vfdprintf on any version by renaming those calls to their
  * legacy equivalents if needed.
  */
-int dprintf(int, const char*, ...) __printflike(2, 3) __RENAME(fdprintf);
-int vdprintf(int, const char*, va_list) __printflike(2, 0) __RENAME(vfdprintf);
+int dprintf(int, const char*, ...) __RENAME(fdprintf) __printflike(2, 3);
+int vdprintf(int, const char*, va_list) __RENAME(vfdprintf) __printflike(2, 0);
 #endif
 
 #if (defined(__STDC_VERSION__) && __STDC_VERSION__ < 201112L) || \
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index 3c5abc3..66a3ab9 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -32,22 +32,23 @@
 #include <sys/cdefs.h>
 #include <stdio.h>
 
-#define FSETLOCKING_QUERY 0
-#define FSETLOCKING_INTERNAL 1
-#define FSETLOCKING_BYCALLER 2
 
 __BEGIN_DECLS
 
-size_t __fbufsize(FILE*) __INTRODUCED_IN(23);
-int __freadable(FILE*) __INTRODUCED_IN(23);
-int __freading(FILE*) __INTRODUCED_IN_FUTURE;
-int __fwritable(FILE*) __INTRODUCED_IN(23);
-int __fwriting(FILE*) __INTRODUCED_IN_FUTURE;
-int __flbf(FILE*) __INTRODUCED_IN(23);
-void __fpurge(FILE*) __INTRODUCED_IN(23);
-size_t __fpending(FILE*) __INTRODUCED_IN(23);
+size_t __fbufsize(FILE* __fp) __INTRODUCED_IN(23);
+int __freadable(FILE* __fp) __INTRODUCED_IN(23);
+int __freading(FILE* __fp) __INTRODUCED_IN_FUTURE;
+int __fwritable(FILE* __fp) __INTRODUCED_IN(23);
+int __fwriting(FILE* __fp) __INTRODUCED_IN_FUTURE;
+int __flbf(FILE* __fp) __INTRODUCED_IN(23);
+void __fpurge(FILE* __fp) __INTRODUCED_IN(23);
+size_t __fpending(FILE* __fp) __INTRODUCED_IN(23);
 void _flushlbf(void) __INTRODUCED_IN(23);
-int __fsetlocking(FILE*, int) __INTRODUCED_IN(23);
+
+#define FSETLOCKING_QUERY 0
+#define FSETLOCKING_INTERNAL 1
+#define FSETLOCKING_BYCALLER 2
+int __fsetlocking(FILE* __fp, int __type) __INTRODUCED_IN(23);
 
 __END_DECLS
 
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 13c9d37..4182f2d 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -42,115 +42,114 @@
 #define EXIT_SUCCESS 0
 
 __noreturn void abort(void);
-__noreturn void exit(int);
-__noreturn void _Exit(int) __INTRODUCED_IN(21);
-int atexit(void (*)(void));
+__noreturn void exit(int __status);
+__noreturn void _Exit(int __status) __INTRODUCED_IN(21);
+int atexit(void (*__fn)(void));
 
-int at_quick_exit(void (*)(void)) __INTRODUCED_IN(21);
-void quick_exit(int) __noreturn __INTRODUCED_IN(21);
+int at_quick_exit(void (*__fn)(void)) __INTRODUCED_IN(21);
+void quick_exit(int __status) __noreturn __INTRODUCED_IN(21);
 
-char* getenv(const char*);
-int putenv(char*);
-int setenv(const char*, const char*, int);
-int unsetenv(const char*);
+char* getenv(const char* __name);
+int putenv(char* __assignment);
+int setenv(const char* __name, const char* __value, int __overwrite);
+int unsetenv(const char* __name);
 int clearenv(void);
 
-char* mkdtemp(char*);
-char* mktemp(char*) __attribute__((deprecated("mktemp is unsafe, use mkstemp or tmpfile instead")));
+char* mkdtemp(char* __template);
+char* mktemp(char* __template) __attribute__((deprecated("mktemp is unsafe, use mkstemp or tmpfile instead")));
 
-int mkostemp64(char*, int) __INTRODUCED_IN(23);
-int mkostemp(char*, int) __INTRODUCED_IN(23);
-int mkostemps64(char*, int, int) __INTRODUCED_IN(23);
-int mkostemps(char*, int, int) __INTRODUCED_IN(23);
-int mkstemp64(char*) __INTRODUCED_IN(21);
-int mkstemp(char*);
-int mkstemps64(char*, int) __INTRODUCED_IN(23);
-int mkstemps(char*, int);
+int mkostemp64(char* __template, int __flags) __INTRODUCED_IN(23);
+int mkostemp(char* __template, int __flags) __INTRODUCED_IN(23);
+int mkostemps64(char* __template, int __suffix_length, int __flags) __INTRODUCED_IN(23);
+int mkostemps(char* __template, int __suffix_length, int __flags) __INTRODUCED_IN(23);
+int mkstemp64(char* __template) __INTRODUCED_IN(21);
+int mkstemp(char* __template);
+int mkstemps64(char* __template, int __flags) __INTRODUCED_IN(23);
+int mkstemps(char* __template, int __flags);
 
-long strtol(const char *, char **, int);
-long long strtoll(const char *, char **, int);
-unsigned long strtoul(const char *, char **, int);
-unsigned long long strtoull(const char *, char **, int);
+long strtol(const char* __s, char** __end_ptr, int __base);
+long long strtoll(const char* __s, char** __end_ptr, int __base);
+unsigned long strtoul(const char* __s, char** __end_ptr, int __base);
+unsigned long long strtoull(const char* __s, char** __end_ptr, int __base);
 
-int posix_memalign(void** memptr, size_t alignment, size_t size) __INTRODUCED_IN(16);
+int posix_memalign(void** __memptr, size_t __alignment, size_t __size) __INTRODUCED_IN(16);
 
-double strtod(const char*, char**);
-long double strtold(const char*, char**) __INTRODUCED_IN(21);
+double strtod(const char* __s, char** __end_ptr);
+long double strtold(const char* __s, char** __end_ptr) __INTRODUCED_IN(21);
 
-unsigned long strtoul_l(const char*, char**, int, locale_t) __INTRODUCED_IN(26);
+unsigned long strtoul_l(const char* __s, char** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(26);
 
-int atoi(const char*) __attribute_pure__;
-long atol(const char*) __attribute_pure__;
-long long atoll(const char*) __attribute_pure__;
+int atoi(const char* __s) __attribute_pure__;
+long atol(const char* __s) __attribute_pure__;
+long long atoll(const char* __s) __attribute_pure__;
 
-char* realpath(const char* path, char* resolved);
-int system(const char *string);
+char* realpath(const char* __path, char* __resolved);
+int system(const char* __command);
 
-void* bsearch(const void* key, const void* base0, size_t nmemb, size_t size,
-              int (*compar)(const void*, const void*));
+void* bsearch(const void* __key, const void* __base, size_t __nmemb, size_t __size, int (*__comparator)(const void* __lhs, const void* __rhs));
 
-void qsort(void*, size_t, size_t, int (*)(const void*, const void*));
+void qsort(void* __base, size_t __nmemb, size_t __size, int (*__comparator)(const void* __lhs, const void* __rhs));
 
 uint32_t arc4random(void);
-uint32_t arc4random_uniform(uint32_t);
-void arc4random_buf(void*, size_t);
+uint32_t arc4random_uniform(uint32_t __upper_bound);
+void arc4random_buf(void* __buf, size_t __n);
 
 #define RAND_MAX 0x7fffffff
 
-int rand_r(unsigned int*) __INTRODUCED_IN(21);
+int rand_r(unsigned int* __seed_ptr) __INTRODUCED_IN(21);
 
 double drand48(void);
-double erand48(unsigned short[3]);
-long jrand48(unsigned short[3]);
-void lcong48(unsigned short[7]) __INTRODUCED_IN(23);
+double erand48(unsigned short __xsubi[3]);
+long jrand48(unsigned short __xsubi[3]);
+void lcong48(unsigned short __param[7]) __INTRODUCED_IN(23);
 long lrand48(void);
 long mrand48(void);
-long nrand48(unsigned short[3]);
-unsigned short* seed48(unsigned short[3]);
-void srand48(long);
+long nrand48(unsigned short __xsubi[3]);
+unsigned short* seed48(unsigned short __seed16v[3]);
+void srand48(long __seed);
 
-char* initstate(unsigned int, char*, size_t) __INTRODUCED_IN(21);
-char* setstate(char*) __INTRODUCED_IN(21);
+char* initstate(unsigned int __seed, char* __state, size_t __n) __INTRODUCED_IN(21);
+char* setstate(char* __state) __INTRODUCED_IN(21);
 
 int getpt(void);
-int posix_openpt(int) __INTRODUCED_IN(21);
-char* ptsname(int);
-int ptsname_r(int, char*, size_t);
-int unlockpt(int);
+int posix_openpt(int __flags) __INTRODUCED_IN(21);
+char* ptsname(int __fd);
+int ptsname_r(int __fd, char* __buf, size_t __n);
+int unlockpt(int __fd);
 
-int getsubopt(char**, char* const*, char**) __INTRODUCED_IN(26);
+int getsubopt(char** __option, char* const* __tokens, char** __value_ptr) __INTRODUCED_IN(26);
 
 typedef struct {
-    int  quot;
-    int  rem;
+  int quot;
+  int rem;
 } div_t;
 
-div_t div(int, int) __attribute_const__;
+div_t div(int __numerator, int __denominator) __attribute_const__;
 
 typedef struct {
-    long int  quot;
-    long int  rem;
+  long int quot;
+  long int rem;
 } ldiv_t;
 
-ldiv_t ldiv(long, long) __attribute_const__;
+ldiv_t ldiv(long __numerator, long __denominator) __attribute_const__;
 
 typedef struct {
-    long long int  quot;
-    long long int  rem;
+  long long int quot;
+  long long int rem;
 } lldiv_t;
 
-lldiv_t lldiv(long long, long long) __attribute_const__;
+lldiv_t lldiv(long long __numerator, long long __denominator) __attribute_const__;
 
 /* BSD compatibility. */
 const char* getprogname(void) __INTRODUCED_IN(21);
-void setprogname(const char*) __INTRODUCED_IN(21);
+void setprogname(const char* __name) __INTRODUCED_IN(21);
 
-int mblen(const char*, size_t) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
-size_t mbstowcs(wchar_t*, const char*, size_t);
-int mbtowc(wchar_t*, const char*, size_t) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
-int wctomb(char*, wchar_t) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
+int mblen(const char* __s, size_t __n) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
+size_t mbstowcs(wchar_t* __dst, const char* __src, size_t __n);
+int mbtowc(wchar_t* __wc_ptr, const char* __s, size_t __n) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
+int wctomb(char* __dst, wchar_t __wc) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
 
-size_t wcstombs(char*, const wchar_t*, size_t);
+size_t wcstombs(char* __dst, const wchar_t* __src, size_t __n);
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
 size_t __ctype_get_mb_cur_max(void) __INTRODUCED_IN(21);
@@ -169,28 +168,28 @@
 #endif
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
-float strtof(const char*, char**) __INTRODUCED_IN(21);
-double atof(const char*) __attribute_pure__ __INTRODUCED_IN(21);
-int abs(int) __attribute_const__ __INTRODUCED_IN(21);
-long labs(long) __attribute_const__ __INTRODUCED_IN(21);
-long long llabs(long long) __attribute_const__ __INTRODUCED_IN(21);
+float strtof(const char* __s, char** __end_ptr) __INTRODUCED_IN(21);
+double atof(const char* __s) __attribute_pure__ __INTRODUCED_IN(21);
+int abs(int __x) __attribute_const__ __INTRODUCED_IN(21);
+long labs(long __x) __attribute_const__ __INTRODUCED_IN(21);
+long long llabs(long long __x) __attribute_const__ __INTRODUCED_IN(21);
 int rand(void) __INTRODUCED_IN(21);
-void srand(unsigned int) __INTRODUCED_IN(21);
+void srand(unsigned int __seed) __INTRODUCED_IN(21);
 long random(void) __INTRODUCED_IN(21);
-void srandom(unsigned int) __INTRODUCED_IN(21);
-int grantpt(int) __INTRODUCED_IN(21);
+void srandom(unsigned int __seed) __INTRODUCED_IN(21);
+int grantpt(int __fd) __INTRODUCED_IN(21);
 
-long long strtoll_l(const char*, char**, int, locale_t) __INTRODUCED_IN(21);
-unsigned long long strtoull_l(const char*, char**, int, locale_t) __INTRODUCED_IN(21);
-long double strtold_l(const char*, char**, locale_t) __INTRODUCED_IN(21);
+long long strtoll_l(const char* __s, char** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(21);
+unsigned long long strtoull_l(const char* __s, char** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(21);
+long double strtold_l(const char* __s, char** __end_ptr, locale_t __l) __INTRODUCED_IN(21);
 #else
 // Implemented as static inlines before 21.
 #endif
 
 #if __ANDROID_API__ >= __ANDROID_API_O__
-double strtod_l(const char*, char**, locale_t) __INTRODUCED_IN(26);
-float strtof_l(const char*, char**, locale_t) __INTRODUCED_IN(26);
-long strtol_l(const char*, char**, int, locale_t) __INTRODUCED_IN(26);
+double strtod_l(const char* __s, char** __end_ptr, locale_t __l) __INTRODUCED_IN(26);
+float strtof_l(const char* __s, char** __end_ptr, locale_t __l) __INTRODUCED_IN(26);
+long strtol_l(const char* __s, char** __end_ptr, int, locale_t __l) __INTRODUCED_IN(26);
 #else
 // Implemented as static inlines before 26.
 #endif
diff --git a/libc/include/string.h b/libc/include/string.h
index 631b3dd..164146d 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -58,8 +58,11 @@
 char* __strchr_chk(const char*, int, size_t) __INTRODUCED_IN(18);
 #if defined(__USE_GNU)
 #if defined(__cplusplus)
+/* The versioner doesn't handle C++ blocks yet, so manually guarded. */
+#if __ANDROID_API__ >= 24
 extern "C++" char* strchrnul(char*, int) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
 extern "C++" const char* strchrnul(const char*, int) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
+#endif  /* __ANDROID_API__ >= 24 */
 #else
 char* strchrnul(const char*, int) __attribute_pure__ __INTRODUCED_IN(24);
 #endif
@@ -125,8 +128,11 @@
  * It doesn't modify its argument, and in C++ it's const-correct.
  */
 #if defined(__cplusplus)
+/* The versioner doesn't handle C++ blocks yet, so manually guarded. */
+#if __ANDROID_API__ >= 23
 extern "C++" char* basename(char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
 extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
+#endif  /* __ANDROID_API__ >= 23 */
 #else
 char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
 #endif
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 9541520..71d8426 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -239,7 +239,8 @@
 
 #define __BIONIC_FORTIFY_UNKNOWN_SIZE ((size_t) -1)
 
-#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && \
+      (defined(__clang__) || (defined(__OPTIMIZE__) && __OPTIMIZE__ > 0))
 #  define __BIONIC_FORTIFY 1
 #  if _FORTIFY_SOURCE == 2
 #    define __bos_level 1
@@ -281,8 +282,7 @@
 #define __pass_object_size __pass_object_size_n(__bos_level)
 #define __pass_object_size0 __pass_object_size_n(0)
 
-/* FIXME: This should be __BIONIC_FORTIFY, but we don't enable FORTIFY in -O0. */
-#if (defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0) || defined(__BIONIC_DECLARE_FORTIFY_HELPERS)
+#if defined(__BIONIC_FORTIFY) || defined(__BIONIC_DECLARE_FORTIFY_HELPERS)
 #  define __BIONIC_INCLUDE_FORTIFY_HEADERS 1
 #endif
 
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index 8000f03..fff565e 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -50,28 +50,29 @@
 #define LOG_MAKEPRI(fac, pri) ((fac) | (pri))
 
 /* Facilities are currently ignored on Android. */
-#define LOG_KERN     0000
-#define LOG_USER     0010
-#define LOG_MAIL     0020
-#define LOG_DAEMON   0030
-#define LOG_AUTH     0040
-#define LOG_SYSLOG   0050
-#define LOG_LPR      0060
-#define LOG_NEWS     0070
-#define LOG_UUCP     0100
-#define LOG_CRON     0110
-#define LOG_AUTHPRIV 0120
-#define LOG_FTP      0130
-#define LOG_LOCAL0   0200
-#define LOG_LOCAL1   0210
-#define LOG_LOCAL2   0220
-#define LOG_LOCAL3   0230
-#define LOG_LOCAL4   0240
-#define LOG_LOCAL5   0250
-#define LOG_LOCAL6   0260
-#define LOG_LOCAL7   0270
+#define LOG_KERN     (0<<3)
+#define LOG_USER     (1<<3)
+#define LOG_MAIL     (2<<3)
+#define LOG_DAEMON   (3<<3)
+#define LOG_AUTH     (4<<3)
+#define LOG_SYSLOG   (5<<3)
+#define LOG_LPR      (6<<3)
+#define LOG_NEWS     (7<<3)
+#define LOG_UUCP     (8<<3)
+#define LOG_CRON     (9<<3)
+#define LOG_AUTHPRIV (10<<3)
+#define LOG_FTP      (11<<3)
+#define LOG_LOCAL0   (16<<3)
+#define LOG_LOCAL1   (17<<3)
+#define LOG_LOCAL2   (18<<3)
+#define LOG_LOCAL3   (19<<3)
+#define LOG_LOCAL4   (20<<3)
+#define LOG_LOCAL5   (21<<3)
+#define LOG_LOCAL6   (22<<3)
+#define LOG_LOCAL7   (23<<3)
 
-#define LOG_FACMASK 01770
+#define LOG_NFACILITIES 24
+#define LOG_FACMASK 0x3f8
 #define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3))
 
 #define LOG_MASK(pri) (1 << (pri))
@@ -86,10 +87,10 @@
 #define LOG_PERROR 0x20
 
 void closelog(void);
-void openlog(const char*, int, int);
-int setlogmask(int);
-void syslog(int, const char*, ...) __printflike(2, 3);
-void vsyslog(int, const char*, va_list) __printflike(2, 0);
+void openlog(const char* __prefix, int __option, int __facility);
+int setlogmask(int __mask);
+void syslog(int __priority, const char* __fmt, ...) __printflike(2, 3);
+void vsyslog(int __priority, const char* __fmt, va_list __args) __printflike(2, 0);
 
 __END_DECLS
 
diff --git a/libc/include/utmp.h b/libc/include/utmp.h
index 62e8d59..6a52511 100644
--- a/libc/include/utmp.h
+++ b/libc/include/utmp.h
@@ -96,12 +96,12 @@
 
 __BEGIN_DECLS
 
-int utmpname(const char*);
+int utmpname(const char* __path);
 void setutent(void);
 struct utmp* getutent(void);
 void endutent(void);
 
-int login_tty(int) __INTRODUCED_IN(23);
+int login_tty(int __fd) __INTRODUCED_IN(23);
 
 __END_DECLS
 
diff --git a/libc/kernel/uapi/linux/ion.h b/libc/kernel/uapi/linux/ion.h
index 4fa9d2d..7b5b031 100644
--- a/libc/kernel/uapi/linux/ion.h
+++ b/libc/kernel/uapi/linux/ion.h
@@ -20,6 +20,7 @@
 #define _UAPI_LINUX_ION_H
 #include <linux/ioctl.h>
 #include <linux/types.h>
+typedef int ion_user_handle_t;
 enum ion_heap_type {
   ION_HEAP_TYPE_SYSTEM,
   ION_HEAP_TYPE_SYSTEM_CONTIG,
@@ -32,11 +33,22 @@
 #define ION_FLAG_CACHED 1
 #define ION_FLAG_CACHED_NEEDS_SYNC 2
 struct ion_allocation_data {
-  __u64 len;
-  __u32 heap_id_mask;
-  __u32 flags;
-  __u32 fd;
-  __u32 unused;
+  size_t len;
+  size_t align;
+  unsigned int heap_id_mask;
+  unsigned int flags;
+  ion_user_handle_t handle;
+};
+struct ion_fd_data {
+  ion_user_handle_t handle;
+  int fd;
+};
+struct ion_handle_data {
+  ion_user_handle_t handle;
+};
+struct ion_custom_data {
+  unsigned int cmd;
+  unsigned long arg;
 };
 #define MAX_HEAP_NAME 32
 struct ion_heap_data {
@@ -56,5 +68,11 @@
 };
 #define ION_IOC_MAGIC 'I'
 #define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, struct ion_allocation_data)
+#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
+#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
+#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
+#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
+#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
+#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
 #define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, struct ion_heap_query)
 #endif
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index ab7c247..e6240a1 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -568,7 +568,7 @@
 
         # Collect the set of all syscalls for all architectures.
         syscalls = set()
-        pattern = re.compile(r'^\s*#\s*define\s*__NR_([a-z]\S+)')
+        pattern = re.compile(r'^\s*#\s*define\s*__NR_([a-z_]\S+)')
         for unistd_h in ["kernel/uapi/asm-generic/unistd.h",
                          "kernel/uapi/asm-arm/asm/unistd.h",
                          "kernel/uapi/asm-arm/asm/unistd-common.h",
diff --git a/linker/linker.cpp b/linker/linker.cpp
index a212624..8aadd14 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3506,6 +3506,9 @@
   g_default_namespace.set_permitted_paths(default_ns_config->permitted_paths());
 
   namespaces[default_ns_config->name()] = &g_default_namespace;
+  if (default_ns_config->visible()) {
+    g_exported_namespaces[default_ns_config->name()] = &g_default_namespace;
+  }
 
   // 2. Initialize other namespaces
 
diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp
index f18fac5..3a5ef74 100644
--- a/tests/complex_test.cpp
+++ b/tests/complex_test.cpp
@@ -28,7 +28,7 @@
 
 // libc++ actively gets in the way of including <complex.h> from C++, so we
 // have to be naughty.
-#include <../libc/include/complex.h>
+#include "../libc/include/complex.h"
 
 // (libc++ also seems to have really bad implementations of its own that ignore
 // the intricacies of floating point math.)
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index b264e53..0dc54d0 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -824,7 +824,7 @@
   const std::string lib_path = get_testlib_root() + "/libtest_simple.so";
 
   int tmpfd = TEMP_FAILURE_RETRY(
-        open(get_testlib_root().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL));
+        open(get_testlib_root().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL, 0));
 
   // Ignore kernels without O_TMPFILE flag support
   if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index 1bef0f4..4532a4b 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -23,6 +23,8 @@
 
 #include "TemporaryFile.h"
 
+#include <android-base/stringprintf.h>
+
 // Glibc v2.19 doesn't include these in fcntl.h so host builds will fail without.
 #if !defined(FALLOC_FL_PUNCH_HOLE) || !defined(FALLOC_FL_KEEP_SIZE)
 #include <linux/falloc.h>
@@ -292,3 +294,43 @@
     ASSERT_EQ(errno, EOPNOTSUPP);
   }
 }
+
+TEST(fcntl, open_O_TMPFILE_mode) {
+#if __BIONIC__ // Our glibc is too old for O_TMPFILE.
+  TemporaryDir dir;
+  // Without O_EXCL, we're allowed to give this a name later.
+  // (This is unrelated to the O_CREAT interaction with O_EXCL.)
+  const mode_t perms = S_IRUSR | S_IWUSR;
+  int fd = open(dir.dirname, O_TMPFILE | O_RDWR, perms);
+
+  // Ignore kernels without O_TMPFILE support (< 3.11).
+  if (fd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) return;
+
+  ASSERT_TRUE(fd != -1) << strerror(errno);
+
+  // Does the fd claim to have the mode we set?
+  struct stat sb = {};
+  ASSERT_EQ(0, fstat(fd, &sb));
+  ASSERT_EQ(perms, (sb.st_mode & ~S_IFMT));
+
+  std::string final_path = android::base::StringPrintf("%s/named_now", dir.dirname);
+  ASSERT_EQ(0, linkat(AT_FDCWD, android::base::StringPrintf("/proc/self/fd/%d", fd).c_str(),
+                      AT_FDCWD, final_path.c_str(),
+                      AT_SYMLINK_FOLLOW));
+  ASSERT_EQ(0, close(fd));
+
+  // Does the resulting file claim to have the mode we set?
+  ASSERT_EQ(0, stat(final_path.c_str(), &sb));
+  ASSERT_EQ(perms, (sb.st_mode & ~S_IFMT));
+
+  // With O_EXCL, you're not allowed to add a name later.
+  fd = open(dir.dirname, O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
+  ASSERT_TRUE(fd != -1) << strerror(errno);
+  errno = 0;
+  ASSERT_EQ(-1, linkat(AT_FDCWD, android::base::StringPrintf("/proc/self/fd/%d", fd).c_str(),
+                       AT_FDCWD, android::base::StringPrintf("%s/no_chance", dir.dirname).c_str(),
+                       AT_SYMLINK_FOLLOW));
+  ASSERT_EQ(ENOENT, errno);
+  ASSERT_EQ(0, close(fd));
+#endif
+}
diff --git a/tests/fortify_compilation_test.cpp b/tests/fortify_compilation_test.cpp
index db800a2..7517fde 100644
--- a/tests/fortify_compilation_test.cpp
+++ b/tests/fortify_compilation_test.cpp
@@ -224,14 +224,28 @@
 
 void test_open() {
   // NOLINTNEXTLINE(whitespace/line_length)
-  // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT, but missing mode
-  // CLANG: error: 'open' called with O_CREAT, but missing mode
+  // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT or O_TMPFILE, but missing mode
+  // CLANG: error: 'open' called with O_CREAT or O_TMPFILE, but missing mode
   open("/dev/null", O_CREAT);
 
+  // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT or O_TMPFILE, but missing mode
+  // CLANG: error: 'open' called with O_CREAT or O_TMPFILE, but missing mode
+  open("/dev/null", O_TMPFILE);
+
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__creat_too_many_args' declared with attribute error: too many arguments
   // CLANG: error: call to unavailable function 'open': too many arguments
   open("/dev/null", O_CREAT, 0, 0);
+
+  // GCC: error: call to '__creat_too_many_args' declared with attribute error: too many arguments
+  // CLANG: error: call to unavailable function 'open': too many arguments
+  open("/dev/null", O_TMPFILE, 0, 0);
+
+  // CLANG: warning: 'open' has superfluous mode bits; missing O_CREAT?
+  open("/dev/null", O_RDONLY, 0644);
+
+  // CLANG: warning: 'open' has superfluous mode bits; missing O_CREAT?
+  open("/dev/null", O_DIRECTORY, 0644);
 }
 
 void test_poll() {
@@ -362,6 +376,7 @@
   // This is fine.
   realpath(".", NULL);
 
-  // FIXME: But we should warn on this.
-  realpath(NULL, buf);
+  char bigbuf[PATH_MAX];
+  // CLANG: error: 'realpath': NULL path is never correct; flipped arguments?
+  realpath(NULL, bigbuf);
 }
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 984a657..2946e23 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -985,3 +985,15 @@
   timeout.tv_sec = timeout.tv_nsec = 0;
   ASSERT_FORTIFY(ppoll(buf, fd_count, &timeout, NULL));
 }
+
+TEST_F(DEATHTEST, open_O_CREAT_without_mode_fortified) {
+  int flags = O_CREAT; // Fool the compiler.
+  ASSERT_FORTIFY(open("", flags));
+}
+
+TEST_F(DEATHTEST, open_O_TMPFILE_without_mode_fortified) {
+#if __BIONIC__ // Our glibc is too old for O_TMPFILE.
+  int flags = O_TMPFILE; // Fool the compiler.
+  ASSERT_FORTIFY(open("", flags));
+#endif
+}
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index f8232aa..b8df8e7 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -207,7 +207,14 @@
       application = true;
     } else {
       ASSERT_STREQ("/", pwd->pw_dir);
-      ASSERT_FALSE(exist[pwd->pw_uid]);
+      // TODO(b/27999086): fix this check with the OEM range
+      // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
+      // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
+      // yet, so therefore we do not check for uid's in the OEM range.
+      if (!(pwd->pw_uid >= 2900 && pwd->pw_uid <= 2999) &&
+          !(pwd->pw_uid >= 5000 && pwd->pw_uid <= 5999)) {
+        ASSERT_FALSE(exist[pwd->pw_uid]);
+      }
       exist[pwd->pw_uid] = true;
     }
   }
@@ -453,7 +460,14 @@
     if (grp->gr_gid >= exist.size()) {
       application = true;
     } else {
-      ASSERT_FALSE(exist[grp->gr_gid]);
+      // TODO(b/27999086): fix this check with the OEM range
+      // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
+      // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
+      // yet, so therefore we do not check for gid's in the OEM range.
+      if (!(grp->gr_gid >= 2900 && grp->gr_gid <= 2999) &&
+          !(grp->gr_gid >= 5000 && grp->gr_gid <= 5999)) {
+        ASSERT_FALSE(exist[grp->gr_gid]);
+      }
       exist[grp->gr_gid] = true;
     }
   }
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 1bb97a3..7b7737d 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -556,6 +556,45 @@
               L"[-NAN]", L"[NAN]", L"[+NAN]");
 }
 
+TEST(STDIO_TEST, swprintf) {
+  constexpr size_t nchars = 32;
+  wchar_t buf[nchars];
+
+  ASSERT_EQ(2, swprintf(buf, nchars, L"ab")) << strerror(errno);
+  ASSERT_EQ(std::wstring(L"ab"), buf);
+  ASSERT_EQ(5, swprintf(buf, nchars, L"%s", "abcde"));
+  ASSERT_EQ(std::wstring(L"abcde"), buf);
+
+  // Unlike swprintf(), swprintf() returns -1 in case of truncation
+  // and doesn't necessarily zero-terminate the output!
+  ASSERT_EQ(-1, swprintf(buf, 4, L"%s", "abcde"));
+
+  const char kString[] = "Hello, World";
+  ASSERT_EQ(12, swprintf(buf, nchars, L"%s", kString));
+  ASSERT_EQ(std::wstring(L"Hello, World"), buf);
+  ASSERT_EQ(12, swprintf(buf, 13, L"%s", kString));
+  ASSERT_EQ(std::wstring(L"Hello, World"), buf);
+}
+
+TEST(STDIO_TEST, swprintf_a) {
+  constexpr size_t nchars = 32;
+  wchar_t buf[nchars];
+
+  ASSERT_EQ(20, swprintf(buf, nchars, L"%a", 3.1415926535));
+  ASSERT_EQ(std::wstring(L"0x1.921fb54411744p+1"), buf);
+}
+
+TEST(STDIO_TEST, swprintf_ls) {
+  constexpr size_t nchars = 32;
+  wchar_t buf[nchars];
+
+  static const wchar_t kWideString[] = L"Hello\uff41 World";
+  ASSERT_EQ(12, swprintf(buf, nchars, L"%ls", kWideString));
+  ASSERT_EQ(std::wstring(kWideString), buf);
+  ASSERT_EQ(12, swprintf(buf, 13, L"%ls", kWideString));
+  ASSERT_EQ(std::wstring(kWideString), buf);
+}
+
 TEST(STDIO_TEST, snprintf_d_INT_MAX) {
   char buf[BUFSIZ];
   snprintf(buf, sizeof(buf), "%d", INT_MAX);
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index c724f74..7d2dc20 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -184,7 +184,9 @@
 
 TEST(stdlib, realpath__NULL_filename) {
   errno = 0;
-  char* p = realpath(NULL, NULL);
+  // Work around the compile-time error generated by FORTIFY here.
+  const char* path = NULL;
+  char* p = realpath(path, NULL);
   ASSERT_TRUE(p == NULL);
   ASSERT_EQ(EINVAL, errno);
 }
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index a795d2c..a7e49e8 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -17,6 +17,7 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <locale.h>
 #include <stdint.h>
@@ -406,20 +407,98 @@
   ASSERT_EQ('\x20', *invalid);
 }
 
-TEST(wchar, wcstol) {
-  ASSERT_EQ(123L, wcstol(L"123", NULL, 0));
+template <typename T>
+using WcsToIntFn = T (*)(const wchar_t*, wchar_t**, int);
+
+template <typename T>
+void TestSingleWcsToInt(WcsToIntFn<T> fn, const wchar_t* str, int base,
+                        T expected_value, ptrdiff_t expected_len) {
+  wchar_t* p;
+  ASSERT_EQ(expected_value, fn(str, &p, base));
+  ASSERT_EQ(expected_len, p - str) << str;
 }
 
-TEST(wchar, wcstoll) {
-  ASSERT_EQ(123LL, wcstol(L"123", NULL, 0));
+template <typename T>
+void TestWcsToInt(WcsToIntFn<T> fn) {
+  TestSingleWcsToInt(fn, L"123", 10, static_cast<T>(123), 3);
+  TestSingleWcsToInt(fn, L"123", 0, static_cast<T>(123), 3);
+  TestSingleWcsToInt(fn, L"123#", 10, static_cast<T>(123), 3);
+  TestSingleWcsToInt(fn, L"01000", 8, static_cast<T>(512), 5);
+  TestSingleWcsToInt(fn, L"01000", 0, static_cast<T>(512), 5);
+  TestSingleWcsToInt(fn, L"   123 45", 0, static_cast<T>(123), 6);
+  TestSingleWcsToInt(fn, L"  -123", 0, static_cast<T>(-123), 6);
+  TestSingleWcsToInt(fn, L"0x10000", 0, static_cast<T>(65536), 7);
+}
+
+template <typename T>
+void TestWcsToIntLimits(WcsToIntFn<T> fn, const wchar_t* min_str,
+                        const wchar_t* max_str) {
+  if (std::is_signed<T>::value) {
+    ASSERT_EQ(std::numeric_limits<T>::min(), fn(min_str, nullptr, 0)) << min_str;
+  } else {
+    // If the subject sequence begins with a <hyphen-minus>, the value resulting
+    // from the conversion shall be negated.
+    // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html
+    ASSERT_EQ(std::numeric_limits<T>::max(), fn(min_str, nullptr, 0)) << min_str;
+  }
+  ASSERT_EQ(std::numeric_limits<T>::max(), fn(max_str, nullptr, 0)) << max_str;
+}
+
+TEST(wchar, wcstol) {
+  TestWcsToInt(wcstol);
+}
+
+TEST(wchar, wcstol_limits) {
+  if (sizeof(long) == 8) {
+    TestWcsToIntLimits(wcstol, L"-9223372036854775809", L"9223372036854775808");
+  } else {
+    TestWcsToIntLimits(wcstol, L"-2147483649", L"2147483648");
+  }
 }
 
 TEST(wchar, wcstoul) {
-  ASSERT_EQ(123UL, wcstoul(L"123", NULL, 0));
+  TestWcsToInt(wcstoul);
+}
+
+TEST(wchar, wcstoul_limits) {
+  if (sizeof(long) == 8) {
+    TestWcsToIntLimits(wcstoul, L"-1", L"18446744073709551616");
+  } else {
+    TestWcsToIntLimits(wcstoul, L"-1", L"4294967296");
+  }
+}
+
+TEST(wchar, wcstoll) {
+  TestWcsToInt(wcstoll);
+}
+
+TEST(wchar, wcstoll_limits) {
+  TestWcsToIntLimits(wcstoll, L"-9223372036854775809", L"9223372036854775808");
 }
 
 TEST(wchar, wcstoull) {
-  ASSERT_EQ(123ULL, wcstoul(L"123", NULL, 0));
+  TestWcsToInt(wcstoull);
+}
+
+TEST(wchar, wcstoull_limits) {
+  TestWcsToIntLimits(wcstoull, L"-1", L"18446744073709551616");
+}
+
+TEST(wchar, wcstoimax) {
+  TestWcsToInt(wcstoimax);
+}
+
+TEST(wchar, wcstoimax_limits) {
+  TestWcsToIntLimits(wcstoimax, L"-9223372036854775809",
+                     L"9223372036854775808");
+}
+
+TEST(wchar, wcstoumax) {
+  TestWcsToInt(wcstoumax);
+}
+
+TEST(wchar, wcstoumax_limits) {
+  TestWcsToIntLimits(wcstoumax, L"-1", L"18446744073709551616");
 }
 
 TEST(wchar, mbsnrtowcs) {
@@ -691,68 +770,111 @@
 }
 
 template <typename T>
-static void CheckWcsToFloat(T fn(const wchar_t* s, wchar_t** end)) {
-  FpUlpEq<0, T> pred;
+using WcsToFloatFn = T (*)(const wchar_t*, wchar_t**);
 
-  EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"9.0", nullptr));
-  EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0.9e1", nullptr));
-  EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0x1.2p3", nullptr));
-
-  const wchar_t* s = L" \t\v\f\r\n9.0";
+template <typename T>
+void TestSingleWcsToFloat(WcsToFloatFn<T> fn, const wchar_t* str,
+                          T expected_value, ptrdiff_t expected_len) {
   wchar_t* p;
-  EXPECT_PRED_FORMAT2(pred, 9.0, fn(s, &p));
-  EXPECT_EQ(s + wcslen(s), p);
-
-  EXPECT_TRUE(isnan(fn(L"+nan", nullptr)));
-  EXPECT_TRUE(isnan(fn(L"nan", nullptr)));
-  EXPECT_TRUE(isnan(fn(L"-nan", nullptr)));
-
-  EXPECT_TRUE(isnan(fn(L"+nan(0xff)", nullptr)));
-  EXPECT_TRUE(isnan(fn(L"nan(0xff)", nullptr)));
-  EXPECT_TRUE(isnan(fn(L"-nan(0xff)", nullptr)));
-
-  EXPECT_TRUE(isnan(fn(L"+nanny", &p)));
-  EXPECT_STREQ(L"ny", p);
-  EXPECT_TRUE(isnan(fn(L"nanny", &p)));
-  EXPECT_STREQ(L"ny", p);
-  EXPECT_TRUE(isnan(fn(L"-nanny", &p)));
-  EXPECT_STREQ(L"ny", p);
-
-  EXPECT_EQ(0, fn(L"muppet", &p));
-  EXPECT_STREQ(L"muppet", p);
-  EXPECT_EQ(0, fn(L"  muppet", &p));
-  EXPECT_STREQ(L"  muppet", p);
-
-  EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"+inf", nullptr));
-  EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"inf", nullptr));
-  EXPECT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-inf", nullptr));
-
-  EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinity", nullptr));
-  EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinity", nullptr));
-  EXPECT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinity", nullptr));
-
-  EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinitude", &p));
-  EXPECT_STREQ(L"initude", p);
-  EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinitude", &p));
-  EXPECT_STREQ(L"initude", p);
-  EXPECT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinitude", &p));
-  EXPECT_STREQ(L"initude", p);
-
-  // Check case-insensitivity.
-  EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"InFiNiTy", nullptr));
-  EXPECT_TRUE(isnan(fn(L"NaN", nullptr)));
+  ASSERT_EQ(expected_value, fn(str, &p));
+  ASSERT_EQ(expected_len, p - str);
 }
 
-TEST(wchar, wcstod) {
-  CheckWcsToFloat(wcstod);
+template <typename T>
+void TestWcsToFloat(WcsToFloatFn<T> fn) {
+  TestSingleWcsToFloat(fn, L"123", static_cast<T>(123.0), 3);
+  TestSingleWcsToFloat(fn, L"123#", static_cast<T>(123.0), 3);
+  TestSingleWcsToFloat(fn, L"   123 45", static_cast<T>(123.0), 6);
+  TestSingleWcsToFloat(fn, L"9.0", static_cast<T>(9.0), 3);
+  TestSingleWcsToFloat(fn, L"-9.0", static_cast<T>(-9.0), 4);
+  TestSingleWcsToFloat(fn, L" \t\v\f\r\n9.0", static_cast<T>(9.0), 9);
+}
+
+template <typename T>
+void TestWcsToFloatHexFloats(WcsToFloatFn<T> fn) {
+  TestSingleWcsToFloat(fn, L"0.9e1", static_cast<T>(9.0), 5);
+  TestSingleWcsToFloat(fn, L"0x1.2p3", static_cast<T>(9.0), 7);
+  TestSingleWcsToFloat(fn, L"+1e+100", static_cast<T>(1e100), 7);
+  TestSingleWcsToFloat(fn, L"0x10000.80", static_cast<T>(65536.50), 10);
+}
+
+template <typename T>
+void TestWcsToFloatInfNan(WcsToFloatFn<T> fn) {
+  ASSERT_TRUE(isnan(fn(L"+nan", nullptr)));
+  ASSERT_TRUE(isnan(fn(L"nan", nullptr)));
+  ASSERT_TRUE(isnan(fn(L"-nan", nullptr)));
+
+  ASSERT_TRUE(isnan(fn(L"+nan(0xff)", nullptr)));
+  ASSERT_TRUE(isnan(fn(L"nan(0xff)", nullptr)));
+  ASSERT_TRUE(isnan(fn(L"-nan(0xff)", nullptr)));
+
+  wchar_t* p;
+  ASSERT_TRUE(isnan(fn(L"+nanny", &p)));
+  ASSERT_STREQ(L"ny", p);
+  ASSERT_TRUE(isnan(fn(L"nanny", &p)));
+  ASSERT_STREQ(L"ny", p);
+  ASSERT_TRUE(isnan(fn(L"-nanny", &p)));
+  ASSERT_STREQ(L"ny", p);
+
+  ASSERT_EQ(0, fn(L"muppet", &p));
+  ASSERT_STREQ(L"muppet", p);
+  ASSERT_EQ(0, fn(L"  muppet", &p));
+  ASSERT_STREQ(L"  muppet", p);
+
+  ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+inf", nullptr));
+  ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"inf", nullptr));
+  ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-inf", nullptr));
+
+  ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinity", nullptr));
+  ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinity", nullptr));
+  ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinity", nullptr));
+
+  ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinitude", &p));
+  ASSERT_STREQ(L"initude", p);
+  ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinitude", &p));
+  ASSERT_STREQ(L"initude", p);
+  ASSERT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinitude", &p));
+  ASSERT_STREQ(L"initude", p);
+
+  // Check case-insensitivity.
+  ASSERT_EQ(std::numeric_limits<T>::infinity(), fn(L"InFiNiTy", nullptr));
+  ASSERT_TRUE(isnan(fn(L"NaN", nullptr)));
 }
 
 TEST(wchar, wcstof) {
-  CheckWcsToFloat(wcstof);
+  TestWcsToFloat(wcstof);
+}
+
+TEST(wchar, wcstof_hex_floats) {
+  TestWcsToFloatHexFloats(wcstof);
+}
+
+TEST(wchar, wcstof_hex_inf_nan) {
+  TestWcsToFloatInfNan(wcstof);
+}
+
+TEST(wchar, wcstod) {
+  TestWcsToFloat(wcstod);
+}
+
+TEST(wchar, wcstod_hex_floats) {
+  TestWcsToFloatHexFloats(wcstod);
+}
+
+TEST(wchar, wcstod_hex_inf_nan) {
+  TestWcsToFloatInfNan(wcstod);
 }
 
 TEST(wchar, wcstold) {
-  CheckWcsToFloat(wcstold);
+  TestWcsToFloat(wcstold);
+}
+
+TEST(wchar, wcstold_hex_floats) {
+  TestWcsToFloatHexFloats(wcstold);
+}
+
+TEST(wchar, wcstold_hex_inf_nan) {
+  TestWcsToFloatInfNan(wcstold);
 }
 
 static void AssertWcwidthRange(wchar_t begin, wchar_t end, int expected) {
diff --git a/tools/versioner/src/Driver.cpp b/tools/versioner/src/Driver.cpp
index a094818..8a8e00a 100644
--- a/tools/versioner/src/Driver.cpp
+++ b/tools/versioner/src/Driver.cpp
@@ -119,7 +119,14 @@
 
   cmd.push_back("-DANDROID");
   cmd.push_back("-D__ANDROID_API__="s + std::to_string(type.api_level));
+  // FIXME: Re-enable FORTIFY properly once our clang in external/ is new enough
+  // to support diagnose_if without giving us syntax errors.
+#if 0
   cmd.push_back("-D_FORTIFY_SOURCE=2");
+#else
+  cmd.push_back("-D_FORTIFY_SOURCE=0");
+  cmd.push_back("-D__BIONIC_DECLARE_FORTIFY_HELPERS");
+#endif
   cmd.push_back("-D_GNU_SOURCE");
   cmd.push_back("-D_FILE_OFFSET_BITS="s + std::to_string(type.file_offset_bits));