Improve error handling and fix minor bugs in bionic benchmarks.

Test: Unit tests.
Change-Id: I224ae4c7f195176eb8a87deddb2debcbf0f24ba3
diff --git a/benchmarks/bionic_benchmarks.cpp b/benchmarks/bionic_benchmarks.cpp
index ed5460f..9cec3c4 100644
--- a/benchmarks/bionic_benchmarks.cpp
+++ b/benchmarks/bionic_benchmarks.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <err.h>
 #include <getopt.h>
 #include <math.h>
 #include <sys/resource.h>
@@ -49,7 +50,7 @@
   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("                  [--bionic_extra=\"<fn_name> <arg1> <arg 2> ... ]\n");
   printf("                  [<Google benchmark flags>]\n");
   printf("Google benchmark flags:\n");
 
@@ -58,7 +59,7 @@
   char argv1[] = "--help";
   char* fake_argv[3] {argv0, argv1, NULL};
   benchmark::Initialize(&fake_argc, fake_argv);
-  abort();
+  exit(1);
 }
 
 // This function removes any bionic benchmarks command line arguments by checking them
@@ -113,8 +114,7 @@
           char* check_null;
           opts.cpu_to_lock = strtol(optarg, &check_null, 10);
           if (*check_null) {
-            printf("ERROR: Args %s is not a valid integer.\n", optarg);
-            abort();
+            errx(1, "ERROR: Args %s is not a valid integer.", optarg);
           }
         } else {
           printf("ERROR: no argument specified for bionic_cpu\n");
@@ -141,9 +141,8 @@
         if (*optarg){
           char* check_null;
           opts.num_iterations = strtol(optarg, &check_null, 10);
-          if (*check_null != '\0') {
-            printf("ERROR: Args %s is not a valid integer.\n", optarg);
-            abort();
+          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");
@@ -156,7 +155,7 @@
       case '?':
         break;
       default:
-        abort();
+        exit(1);
     }
   }
   return opts;
@@ -184,8 +183,7 @@
     char* check_null;
     int converted = static_cast<int>(strtol(argstr.c_str(), &check_null, 10));
     if (*check_null) {
-      printf("ERROR: Args str %s contains an invalid macro or int.\n", args.c_str());
-      abort();
+      errx(1, "ERROR: Args str %s contains an invalid macro or int.", args.c_str());
     }
     (*to_populate)[0].push_back(converted);
   }
@@ -195,8 +193,7 @@
 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()) {
-    printf("ERROR:No benchmark for function %s\n", fn_name.c_str());
-    abort();
+    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;
@@ -263,13 +260,11 @@
   while (fn) {
     auto fn_elem = fn->FirstChildElement("name");
     if (!fn_elem) {
-      printf("Error: Malformed XML entry: missing name element.\n");
-      abort();
+      errx(1, "ERROR: Malformed XML entry: missing name element.");
     }
     std::string fn_name = fn_elem->GetText();
     if (fn_name.empty()) {
-      printf("Error: Malformed XML entry: error parsing name text.");
-      abort();
+      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()) : "",
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index a1ca60e..2ab7264 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <err.h>
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>
@@ -68,7 +69,9 @@
   while (state.KeepRunning()) {
     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);
   }
 }
diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp
index 7a12eb6..eb325ab 100644
--- a/benchmarks/stdlib_benchmark.cpp
+++ b/benchmarks/stdlib_benchmark.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <err.h>
 #include <langinfo.h>
 #include <locale.h>
 #include <stdlib.h>
@@ -47,7 +48,9 @@
   || 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")) abort();
+  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);
@@ -86,7 +89,9 @@
   || 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")) abort();
+  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;
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index 94e7583..eb04c93 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <err.h>
 #include <stdint.h>
 #include <string.h>
 
@@ -263,7 +264,7 @@
 
   while (state.KeepRunning()) {
     if (strstr(haystack_aligned, needle_aligned) == nullptr) {
-      abort();
+      errx(1, "ERROR: strstr failed to find valid substring.");
     }
   }
 
@@ -277,10 +278,11 @@
 
   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) {
-      abort();
+      errx(1, "ERROR: strchr found a chr where it should have failed.");
     }
   }
 
diff --git a/benchmarks/util.cpp b/benchmarks/util.cpp
index 0c7254c..92e8243 100644
--- a/benchmarks/util.cpp
+++ b/benchmarks/util.cpp
@@ -16,6 +16,7 @@
 
 #include "util.h"
 
+#include <err.h>
 #include <math.h>
 #include <sched.h>
 #include <stdio.h>
@@ -27,12 +28,10 @@
 // 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) {
   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) {