fdsan: expose functions to get and interpret tags.

Make it easier to write tests in users of fdsan by exposing functions
to allow users to get and interpret the tags.

Test: bionic_unit_tests
Change-Id: Iafa9bcaeb5e4db230f3dfec6f483274f34602694
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 67b3a62..d877172 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -218,7 +218,7 @@
   return result;
 }
 
-static const char* __tag_to_type(uint64_t tag) {
+const char* android_fdsan_get_tag_type(uint64_t tag) {
   uint64_t type = tag >> 56;
   switch (type) {
     case ANDROID_FDSAN_OWNER_TYPE_FILE:
@@ -253,7 +253,7 @@
   }
 }
 
-static uint64_t __tag_to_owner(uint64_t tag) {
+uint64_t android_fdsan_get_tag_value(uint64_t tag) {
   // Lop off the most significant byte and sign extend.
   return static_cast<uint64_t>(static_cast<int64_t>(tag << 8) >> 8);
 }
@@ -266,10 +266,10 @@
 
   uint64_t tag = expected_tag;
   if (!atomic_compare_exchange_strong(&fde->close_tag, &tag, 0)) {
-    const char* expected_type = __tag_to_type(expected_tag);
-    uint64_t expected_owner = __tag_to_owner(expected_tag);
-    const char* actual_type = __tag_to_type(tag);
-    uint64_t actual_owner = __tag_to_owner(tag);
+    const char* expected_type = android_fdsan_get_tag_type(expected_tag);
+    uint64_t expected_owner = android_fdsan_get_tag_value(expected_tag);
+    const char* actual_type = android_fdsan_get_tag_type(tag);
+    uint64_t actual_owner = android_fdsan_get_tag_value(tag);
     if (expected_tag && tag) {
       fdsan_error(
           "attempted to close file descriptor %d, "
@@ -299,6 +299,14 @@
   return rc;
 }
 
+uint64_t android_fdsan_get_owner_tag(int fd) {
+  FdEntry* fde = GetFdEntry(fd);
+  if (!fde) {
+    return 0;
+  }
+  return fde->close_tag;
+}
+
 void android_fdsan_exchange_owner_tag(int fd, uint64_t expected_tag, uint64_t new_tag) {
   FdEntry* fde = GetFdEntry(fd);
   if (!fde) {
@@ -311,18 +319,18 @@
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "owned by %s 0x%" PRIx64 ", was expected to be owned by %s 0x%" PRIx64,
-          fd, __tag_to_type(tag), __tag_to_owner(tag), __tag_to_type(expected_tag),
-          __tag_to_owner(expected_tag));
+          fd, android_fdsan_get_tag_type(tag), android_fdsan_get_tag_value(tag),
+          android_fdsan_get_tag_type(expected_tag), android_fdsan_get_tag_value(expected_tag));
     } else if (expected_tag && !tag) {
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "unowned, was expected to be owned by %s 0x%" PRIx64,
-          fd, __tag_to_type(expected_tag), __tag_to_owner(expected_tag));
+          fd, android_fdsan_get_tag_type(expected_tag), android_fdsan_get_tag_value(expected_tag));
     } else if (!expected_tag && tag) {
       fdsan_error(
           "failed to exchange ownership of file descriptor: fd %d is "
           "owned by %s 0x%" PRIx64 ", was expected to be unowned",
-          fd, __tag_to_type(tag), __tag_to_owner(tag));
+          fd, android_fdsan_get_tag_type(tag), android_fdsan_get_tag_value(tag));
     } else if (!expected_tag && !tag) {
       // This should never happen: our CAS failed, but expected == actual?
       async_safe_fatal(