Add debug logging for memtag level

Test: adb logcat 'libc:D' | grep memtag
Bug: 272596642
Change-Id: I764a0ea4fd71b547d1c5b82a1537e50016578e0f
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index d64d402..0935cd6 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -217,16 +217,13 @@
 // Returns true if there's an environment setting (either sysprop or env var)
 // that should overwrite the ELF note, and places the equivalent heap tagging
 // level into *level.
-static bool get_environment_memtag_setting(HeapTaggingLevel* level) {
+static bool get_environment_memtag_setting(const char* basename, HeapTaggingLevel* level) {
   static const char kMemtagPrognameSyspropPrefix[] = "arm64.memtag.process.";
   static const char kMemtagGlobalSysprop[] = "persist.arm64.memtag.default";
   static const char kMemtagOverrideSyspropPrefix[] =
       "persist.device_config.memory_safety_native.mode_override.process.";
 
-  const char* progname = __libc_shared_globals()->init_progname;
-  if (progname == nullptr) return false;
-
-  const char* basename = __gnu_basename(progname);
+  if (basename == nullptr) return false;
 
   char options_str[PROP_VALUE_MAX];
   char sysprop_name[512];
@@ -237,8 +234,9 @@
                            kMemtagOverrideSyspropPrefix, basename);
   const char* sys_prop_names[] = {sysprop_name, remote_sysprop_name, kMemtagGlobalSysprop};
 
+  const char* source = nullptr;
   if (!get_config_from_env_or_sysprops("MEMTAG_OPTIONS", sys_prop_names, arraysize(sys_prop_names),
-                                       options_str, sizeof(options_str))) {
+                                       options_str, sizeof(options_str), &source)) {
     return false;
   }
 
@@ -249,27 +247,35 @@
   } else if (strcmp("off", options_str) == 0) {
     *level = M_HEAP_TAGGING_LEVEL_TBI;
   } else {
-    async_safe_format_log(
-        ANDROID_LOG_ERROR, "libc",
-        "unrecognized memtag level: \"%s\" (options are \"sync\", \"async\", or \"off\").",
-        options_str);
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                          "%s: unrecognized memtag level in %s: \"%s\" (options are \"sync\", "
+                          "\"async\", or \"off\").",
+                          basename, source, options_str);
     return false;
   }
-
+  async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "%s: chose memtag level \"%s\" from %s.",
+                        basename, options_str, source);
   return true;
 }
 
+static void log_elf_memtag_level(const char* basename, const char* level) {
+  async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "%s: chose memtag level \"%s\" from ELF note",
+                        basename ?: "<unknown>", level);
+}
+
 // Returns the initial heap tagging level. Note: This function will never return
 // M_HEAP_TAGGING_LEVEL_NONE, if MTE isn't enabled for this process we enable
 // M_HEAP_TAGGING_LEVEL_TBI.
 static HeapTaggingLevel __get_heap_tagging_level(const void* phdr_start, size_t phdr_ct,
                                                  uintptr_t load_bias, bool* stack) {
+  const char* progname = __libc_shared_globals()->init_progname;
+  const char* basename = progname ? __gnu_basename(progname) : nullptr;
   unsigned note_val =
       __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
   *stack = note_val & NT_MEMTAG_STACK;
 
   HeapTaggingLevel level;
-  if (get_environment_memtag_setting(&level)) return level;
+  if (get_environment_memtag_setting(basename, &level)) return level;
 
   // Note, previously (in Android 12), any value outside of bits [0..3] resulted
   // in a check-fail. In order to be permissive of further extensions, we
@@ -284,14 +290,17 @@
       // by anyone, but we note it (heh) here for posterity, in case the zero
       // level becomes meaningful, and binaries with this note can be executed
       // on Android 12 devices.
+      log_elf_memtag_level(basename, "off");
       return M_HEAP_TAGGING_LEVEL_TBI;
     case NT_MEMTAG_LEVEL_ASYNC:
+      log_elf_memtag_level(basename, "async");
       return M_HEAP_TAGGING_LEVEL_ASYNC;
     case NT_MEMTAG_LEVEL_SYNC:
     default:
       // We allow future extensions to specify mode 3 (currently unused), with
       // the idea that it might be used for ASYMM mode or something else. On
       // this version of Android, it falls back to SYNC mode.
+      log_elf_memtag_level(basename, "sync");
       return M_HEAP_TAGGING_LEVEL_SYNC;
   }
 }