Use DYNAMIC entries for MTE enablement

Adds support for the dynamic entries to specify MTE enablement. This is
now the preferred way for dynamically linked executables to specify to
the loader what mode MTE should be in, and whether stack MTE should be
enabled. In future, this is also needed for MTE globals support.

Leave the existing ELF note parsing as a backup option because dynamic
entries are not supported for fully static executables, and there's
still a bunch of glue sitting around in the build system and tests that
explicitly include the note. When -fsanitize=memtag* is specified, lld
will create the note implicitly (along with the new dynamic entries),
but at some point once we've cleaned up all the old references to the
note, we can remove the notegen from lld.

Bug: N/A
Test: atest bionic-unit-tests CtsBionicTestCases --test-filter=*Memtag*
Test: Build/boot the device under _fullmte.

Change-Id: I954b7e78afa5ff4274a3948b968cfad8eba94d88
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 9c589d6..622719d 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -34,9 +34,11 @@
 #include <string>
 #include <vector>
 
-#include "private/bionic_elf_tls.h"
+#include "async_safe/CHECK.h"
 #include "linker_namespaces.h"
 #include "linker_tls.h"
+#include "private/bionic_elf_tls.h"
+#include "private/bionic_globals.h"
 
 #define FLAG_LINKED           0x00000001
 #define FLAG_EXE              0x00000004 // The main executable
@@ -351,6 +353,17 @@
   void set_gap_size(size_t gap_size);
   size_t get_gap_size() const;
 
+  const memtag_dynamic_entries_t* memtag_dynamic_entries() const {
+    CHECK(has_min_version(7));
+    return &memtag_dynamic_entries_;
+  }
+  void* memtag_globals() const { return memtag_dynamic_entries()->memtag_globals; }
+  size_t memtag_globalssz() const { return memtag_dynamic_entries()->memtag_globalssz; }
+  bool has_memtag_mode() const { return memtag_dynamic_entries()->has_memtag_mode; }
+  unsigned memtag_mode() const { return memtag_dynamic_entries()->memtag_mode; }
+  bool memtag_heap() const { return memtag_dynamic_entries()->memtag_heap; }
+  bool memtag_stack() const { return memtag_dynamic_entries()->memtag_stack; }
+
  private:
   bool is_image_linked() const;
   void set_image_linked();
@@ -433,6 +446,9 @@
   // version >= 6
   ElfW(Addr) gap_start_;
   size_t gap_size_;
+
+  // version >= 7
+  memtag_dynamic_entries_t memtag_dynamic_entries_;
 };
 
 // This function is used by dlvsym() to calculate hash of sym_ver