Merge "Simpleperf: add option to report branch stack information."
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"));
+}
diff --git a/squashfs_utils/mksquashfsimage.sh b/squashfs_utils/mksquashfsimage.sh
index 7f96cb1..dab80ba 100755
--- a/squashfs_utils/mksquashfsimage.sh
+++ b/squashfs_utils/mksquashfsimage.sh
@@ -5,7 +5,7 @@
 function usage() {
 cat<<EOT
 Usage:
-${0##*/} SRC_DIR OUTPUT_FILE [-m MOUNT_POINT] [-c FILE_CONTEXTS] [-b BLOCK_SIZE]
+${0##*/} SRC_DIR OUTPUT_FILE [-s] [-m MOUNT_POINT] [-c FILE_CONTEXTS] [-b BLOCK_SIZE]
 EOT
 }
 
@@ -24,6 +24,12 @@
 OUTPUT_FILE=$2
 shift; shift
 
+SPARSE=false
+if [[ "$1" == "-s" ]]; then
+    SPARSE=true
+    shift;
+fi
+
 MOUNT_POINT=
 if [[ "$1" == "-m" ]]; then
     MOUNT_POINT=$2
@@ -53,9 +59,20 @@
   OPT="$OPT -b $BLOCK_SIZE"
 fi
 
-MAKE_SQUASHFS_CMD="mksquashfs $SRC_DIR $OUTPUT_FILE -no-progress -comp lz4 -Xhc -no-exports -noappend -no-recovery -android-fs-config $OPT"
+MAKE_SQUASHFS_CMD="mksquashfs $SRC_DIR/ $OUTPUT_FILE -no-progress -comp lz4 -Xhc -no-exports -noappend -no-recovery -android-fs-config $OPT"
 echo $MAKE_SQUASHFS_CMD
 $MAKE_SQUASHFS_CMD
+
 if [ $? -ne 0 ]; then
     exit 4
 fi
+
+SPARSE_SUFFIX=".sparse"
+if [ "$SPARSE" = true ]; then
+    img2simg $OUTPUT_FILE $OUTPUT_FILE$SPARSE_SUFFIX
+    if [ $? -ne 0 ]; then
+        exit 4
+    fi
+    mv $OUTPUT_FILE$SPARSE_SUFFIX $OUTPUT_FILE
+fi
+
diff --git a/tests/net_test/multinetwork_base.py b/tests/net_test/multinetwork_base.py
index 8940258..5952d56 100644
--- a/tests/net_test/multinetwork_base.py
+++ b/tests/net_test/multinetwork_base.py
@@ -430,13 +430,12 @@
       raise ValueError("Unknown interface selection mode %s" % mode)
 
   def BuildSocket(self, version, constructor, netid, routing_mode):
-    uid = self.UidForNetid(netid) if routing_mode == "uid" else None
-    with net_test.RunAsUid(uid):
-      family = self.GetProtocolFamily(version)
-      s = constructor(family)
+    s = constructor(self.GetProtocolFamily(version))
 
     if routing_mode not in [None, "uid"]:
       self.SelectInterface(s, netid, routing_mode)
+    elif routing_mode == "uid":
+      os.fchown(s.fileno(), self.UidForNetid(netid), -1)
 
     return s