fdsan: minor refactoring.

Make it easier for other code to parse the fdsan table themselves by
making it so that they can include the bionic_fdsan.h header to get a
struct definition with the layout without bringing in other
dependencies.

Test: treehugger
Change-Id: I3583ef113991234aa83cd193a4eb139ad06737c7
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index b0c38bb..918fd37 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -50,6 +50,60 @@
 
 static constexpr const char* kFdsanPropertyName = "debug.fdsan";
 
+template<size_t inline_fds>
+FdEntry* FdTableImpl<inline_fds>::at(size_t idx) {
+  if (idx < inline_fds) {
+    return &entries[idx];
+  }
+
+  // Try to create the overflow table ourselves.
+  FdTableOverflow* local_overflow = atomic_load(&overflow);
+  if (__predict_false(!local_overflow)) {
+    struct rlimit rlim = { .rlim_max = 32768 };
+    getrlimit(RLIMIT_NOFILE, &rlim);
+    rlim_t max = rlim.rlim_max;
+
+    if (max == RLIM_INFINITY) {
+      // This isn't actually possible (the kernel has a hard limit), but just
+      // in case...
+      max = 32768;
+    }
+
+    if (idx > max) {
+      // This can happen if an fd is created and then the rlimit is lowered.
+      // In this case, just return nullptr and ignore the fd.
+      return nullptr;
+    }
+
+    size_t required_count = max - inline_fds;
+    size_t required_size = sizeof(FdTableOverflow) + required_count * sizeof(FdEntry);
+    size_t aligned_size = __BIONIC_ALIGN(required_size, PAGE_SIZE);
+    size_t aligned_count = (aligned_size - sizeof(FdTableOverflow)) / sizeof(FdEntry);
+
+    void* allocation =
+        mmap(nullptr, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if (allocation == MAP_FAILED) {
+      async_safe_fatal("fdsan: mmap failed: %s", strerror(errno));
+    }
+
+    FdTableOverflow* new_overflow = reinterpret_cast<FdTableOverflow*>(allocation);
+    new_overflow->len = aligned_count;
+
+    if (atomic_compare_exchange_strong(&overflow, &local_overflow, new_overflow)) {
+      local_overflow = new_overflow;
+    } else {
+      // Someone beat us to it. Deallocate and use theirs.
+      munmap(allocation, aligned_size);
+    }
+  }
+
+  size_t offset = idx - inline_fds;
+  if (local_overflow->len < offset) {
+    return nullptr;
+  }
+  return &local_overflow->entries[offset];
+}
+
 void __libc_init_fdsan() {
   constexpr auto default_level = ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE;
   const prop_info* pi = __system_property_find(kFdsanPropertyName);
@@ -77,7 +131,7 @@
       nullptr);
 }
 
-static FdTable<128>* GetFdTable() {
+static FdTable* GetFdTable() {
   if (!__libc_shared_globals) {
     return nullptr;
   }
diff --git a/libc/private/bionic_fdsan.h b/libc/private/bionic_fdsan.h
index b93260b..de14cf8 100644
--- a/libc/private/bionic_fdsan.h
+++ b/libc/private/bionic_fdsan.h
@@ -38,8 +38,6 @@
 #include <sys/resource.h>
 #include <sys/user.h>
 
-#include <async_safe/log.h>
-
 struct FdEntry {
   _Atomic(uint64_t) close_tag;
 };
@@ -50,62 +48,14 @@
 };
 
 template <size_t inline_fds>
-struct FdTable {
+struct FdTableImpl {
+  uint32_t version;  // currently 0, and hopefully it'll stay that way.
   _Atomic(android_fdsan_error_level) error_level;
 
   FdEntry entries[inline_fds];
   _Atomic(FdTableOverflow*) overflow;
 
-  FdEntry* at(size_t idx) {
-    if (idx < inline_fds) {
-      return &entries[idx];
-    }
-
-    // Try to create the overflow table ourselves.
-    FdTableOverflow* local_overflow = atomic_load(&overflow);
-    if (__predict_false(!local_overflow)) {
-      struct rlimit rlim = { .rlim_max = 32768 };
-      getrlimit(RLIMIT_NOFILE, &rlim);
-      rlim_t max = rlim.rlim_max;
-
-      if (max == RLIM_INFINITY) {
-        // This isn't actually possible (the kernel has a hard limit), but just
-        // in case...
-        max = 32768;
-      }
-
-      if (idx > max) {
-        // This can happen if an fd is created and then the rlimit is lowered.
-        // In this case, just return nullptr and ignore the fd.
-        return nullptr;
-      }
-
-      size_t required_count = max - inline_fds;
-      size_t required_size = sizeof(FdTableOverflow) + required_count * sizeof(FdEntry);
-      size_t aligned_size = __BIONIC_ALIGN(required_size, PAGE_SIZE);
-      size_t aligned_count = (aligned_size - sizeof(FdTableOverflow)) / sizeof(FdEntry);
-
-      void* allocation =
-          mmap(nullptr, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-      if (allocation == MAP_FAILED) {
-        async_safe_fatal("fdsan: mmap failed: %s", strerror(errno));
-      }
-
-      FdTableOverflow* new_overflow = reinterpret_cast<FdTableOverflow*>(allocation);
-      new_overflow->len = aligned_count;
-
-      if (atomic_compare_exchange_strong(&overflow, &local_overflow, new_overflow)) {
-        local_overflow = new_overflow;
-      } else {
-        // Someone beat us to it. Deallocate and use theirs.
-        munmap(allocation, aligned_size);
-      }
-    }
-
-    size_t offset = idx - inline_fds;
-    if (local_overflow->len < offset) {
-      return nullptr;
-    }
-    return &local_overflow->entries[offset];
-  }
+  FdEntry* at(size_t idx);
 };
+
+using FdTable = FdTableImpl<128>;
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index e569209..eee33c9 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -46,7 +46,7 @@
 
 // Globals shared between the dynamic linker and libc.so.
 struct libc_shared_globals {
-  FdTable<128> fd_table;
+  FdTable fd_table;
 };
 
 __LIBC_HIDDEN__ extern libc_shared_globals* __libc_shared_globals;