Simpleperf: exclude meaningless labels in aarch64.

Also remove the use of <elf.h> because of its conflicts with llvm.

Bug: 19483574
Change-Id: I2cc6fcb3429aa986101e214dc39fabd920f254dd
diff --git a/simpleperf/read_elf.cpp b/simpleperf/read_elf.cpp
index 5fb94e5..4d41165 100644
--- a/simpleperf/read_elf.cpp
+++ b/simpleperf/read_elf.cpp
@@ -32,10 +32,11 @@
 
 #pragma clang diagnostic pop
 
-#include <elf.h>
-
 #include "utils.h"
 
+#define ELF_NOTE_GNU "GNU"
+#define NT_GNU_BUILD_ID 3
+
 static bool GetBuildIdFromNoteSection(const char* section, size_t section_size, BuildId* build_id) {
   const char* p = section;
   const char* end = p + section_size;
@@ -77,7 +78,7 @@
 bool GetBuildIdFromELFFile(const llvm::object::ELFFile<ELFT>* elf, BuildId* build_id) {
   for (auto section_iterator = elf->begin_sections(); section_iterator != elf->end_sections();
        ++section_iterator) {
-    if (section_iterator->sh_type == SHT_NOTE) {
+    if (section_iterator->sh_type == llvm::ELF::SHT_NOTE) {
       auto contents = elf->getSectionContents(&*section_iterator);
       if (contents.getError()) {
         LOG(DEBUG) << "read note section error";
@@ -114,10 +115,19 @@
   }
   return result;
 }
+
+bool IsArmMappingSymbol(const char* name) {
+  // Mapping symbols in arm, which are described in "ELF for ARM Architecture" and
+  // "ELF for ARM 64-bit Architecture". The regular expression to match mapping symbol
+  // is ^\$(a|d|t|x)(\..*)?$
+  return name[0] == '$' && strchr("adtx", name[1]) != nullptr && (name[2] == '\0' || name[2] == '.');
+}
+
 template <class ELFT>
 bool ParseSymbolsFromELFFile(const llvm::object::ELFFile<ELFT>* elf,
                              std::function<void(const ElfFileSymbol&)> callback) {
-  bool is_arm = (elf->getHeader()->e_machine == EM_ARM);
+  bool is_arm = (elf->getHeader()->e_machine == llvm::ELF::EM_ARM ||
+                 elf->getHeader()->e_machine == llvm::ELF::EM_AARCH64);
   auto begin = elf->begin_symbols();
   auto end = elf->end_symbols();
   if (begin == end) {
@@ -158,16 +168,17 @@
     }
     symbol.len = elf_symbol.st_size;
     int type = elf_symbol.getType();
-    if (type == STT_FUNC) {
+    if (type == llvm::ELF::STT_FUNC) {
       symbol.is_func = true;
-    } else if (type == STT_NOTYPE) {
+    } else if (type == llvm::ELF::STT_NOTYPE) {
       if (symbol.is_in_text_section) {
         symbol.is_label = true;
-
-        // Arm has meaningless labels like $t, $d, $x, exclude them.
         if (is_arm) {
-          size_t test_pos = (symbol.name.find(linker_prefix) == 0) ? linker_prefix.size() : 0;
-          if (test_pos + 2 == symbol.name.size() && symbol.name[test_pos] == '$') {
+          // Remove mapping symbols in arm.
+          const char* p = (symbol.name.compare(0, linker_prefix.size(), linker_prefix) == 0)
+                              ? symbol.name.c_str() + linker_prefix.size()
+                              : symbol.name.c_str();
+          if (IsArmMappingSymbol(p)) {
             symbol.is_label = false;
           }
         }
diff --git a/simpleperf/read_elf.h b/simpleperf/read_elf.h
index 487fc28..96eb2f3 100644
--- a/simpleperf/read_elf.h
+++ b/simpleperf/read_elf.h
@@ -39,4 +39,7 @@
 bool ParseSymbolsFromElfFile(const std::string& filename,
                              std::function<void(const ElfFileSymbol&)> callback);
 
+// Expose the following functions for unit tests.
+bool IsArmMappingSymbol(const char* name);
+
 #endif  // SIMPLE_PERF_READ_ELF_H_
diff --git a/simpleperf/read_elf_test.cpp b/simpleperf/read_elf_test.cpp
index bc9ef73..c0ff660 100644
--- a/simpleperf/read_elf_test.cpp
+++ b/simpleperf/read_elf_test.cpp
@@ -36,3 +36,10 @@
       ParseSymbolsFromElfFile(elf_file, std::bind(ParseSymbol, std::placeholders::_1, &result)));
   ASSERT_TRUE(result);
 }
+
+TEST(read_elf, arm_mapping_symbol) {
+  ASSERT_TRUE(IsArmMappingSymbol("$a"));
+  ASSERT_FALSE(IsArmMappingSymbol("$b"));
+  ASSERT_TRUE(IsArmMappingSymbol("$a.anything"));
+  ASSERT_FALSE(IsArmMappingSymbol("$a_no_dot"));
+}