Merge "Move Timer from init to libbase"
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index a4c2160..344fa9a 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -85,12 +85,13 @@
   fprintf(stderr, "Usage: %s [options]\n", cmd);
   fprintf(stderr,
           "options include:\n"
-          "  -h, --help            Show this help\n"
-          "  -l, --log             Log all metrics to logstorage\n"
-          "  -p, --print           Dump the boot event records to the console\n"
-          "  -r, --record          Record the timestamp of a named boot event\n"
-          "  --value               Optional value to associate with the boot event\n"
-          "  --record_boot_reason  Record the reason why the device booted\n"
+          "  -h, --help              Show this help\n"
+          "  -l, --log               Log all metrics to logstorage\n"
+          "  -p, --print             Dump the boot event records to the console\n"
+          "  -r, --record            Record the timestamp of a named boot event\n"
+          "  --value                 Optional value to associate with the boot event\n"
+          "  --record_boot_complete  Record metrics related to the time for the device boot\n"
+          "  --record_boot_reason    Record the reason why the device booted\n"
           "  --record_time_since_factory_reset Record the time since the device was reset\n");
 }
 
diff --git a/include/ziparchive b/include/ziparchive
deleted file mode 120000
index d8fa424..0000000
--- a/include/ziparchive
+++ /dev/null
@@ -1 +0,0 @@
-../libziparchive/include/ziparchive
\ No newline at end of file
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 3a215e9..d01708d 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -161,7 +161,7 @@
 #endif
 
 #if __ANDROID_USE_LIBLOG_CLOCK_INTERFACE
-clockid_t android_log_clockid();
+clockid_t android_log_clockid(void);
 #endif
 
 #endif /* __linux__ */
@@ -185,7 +185,7 @@
  * May be used to clean up File descriptors after a Fork, the resources are
  * all O_CLOEXEC so wil self clean on exec().
  */
-void __android_log_close();
+void __android_log_close(void);
 #endif
 
 #ifndef __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE
diff --git a/libmemunreachable/tests/AndroidTest.xml b/libmemunreachable/tests/AndroidTest.xml
new file mode 100644
index 0000000..604c0ec
--- /dev/null
+++ b/libmemunreachable/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for memunreachable_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="memunreachable_test->/data/local/tmp/memunreachable_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="memunreachable_test" />
+    </test>
+</configuration>
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 377b7dd..1cea4cd 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -1,4 +1,11 @@
 
+cc_library_headers {
+    name: "libnativebridge-dummy-headers",
+
+    host_supported: true,
+    export_include_dirs=["include"],
+}
+
 cc_library {
     name: "libnativebridge",
 
@@ -7,6 +14,8 @@
     shared_libs: ["liblog"],
     clang: true,
 
+    export_include_dirs=["include"],
+
     cflags: [
         "-Werror",
         "-Wall",
@@ -23,4 +32,4 @@
     },
 }
 
-subdirs = ["tests"]
\ No newline at end of file
+subdirs = ["tests"]
diff --git a/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
similarity index 100%
rename from include/nativebridge/native_bridge.h
rename to libnativebridge/include/nativebridge/native_bridge.h
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index efd3978..e31dae0 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -23,6 +23,7 @@
         "-Wextra",
         "-Werror",
     ],
+    header_libs: ["libnativebridge-dummy-headers"],
     cppflags: ["-fvisibility=protected"],
     target: {
         android: {
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 9b8248e..f5d4e1c 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -43,6 +43,9 @@
 
 using namespace std::chrono_literals;
 
+// Uncomment line below use memory cgroups for keeping track of (forked) PIDs
+// #define USE_MEMCG 1
+
 #define MEM_CGROUP_PATH "/dev/memcg/apps"
 #define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks"
 #define ACCT_CGROUP_PATH "/acct"
@@ -88,6 +91,7 @@
 };
 
 static const char* getCgroupRootPath() {
+#ifdef USE_MEMCG
     static const char* cgroup_root_path = NULL;
     std::call_once(init_path_flag, [&]() {
             // Check if mem cgroup is mounted, only then check for write-access to avoid
@@ -96,6 +100,9 @@
                     ACCT_CGROUP_PATH : MEM_CGROUP_PATH;
             });
     return cgroup_root_path;
+#else
+    return ACCT_CGROUP_PATH;
+#endif
 }
 
 static int convertUidToPath(char *path, size_t size, uid_t uid)
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 8776db7..03a9a54 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -98,14 +98,18 @@
         "tests/ElfInterfaceArmTest.cpp",
         "tests/ElfInterfaceTest.cpp",
         "tests/ElfTest.cpp",
+        "tests/ElfTestUtils.cpp",
         "tests/LogFake.cpp",
-        "tests/MapInfoTest.cpp",
+        "tests/MapInfoCreateMemoryTest.cpp",
+        "tests/MapInfoGetElfTest.cpp",
         "tests/MapsTest.cpp",
+        "tests/MemoryBuffer.cpp",
         "tests/MemoryFake.cpp",
         "tests/MemoryFileTest.cpp",
         "tests/MemoryLocalTest.cpp",
         "tests/MemoryRangeTest.cpp",
         "tests/MemoryRemoteTest.cpp",
+        "tests/MemoryTest.cpp",
         "tests/RegsTest.cpp",
         "tests/SymbolsTest.cpp",
     ],
@@ -144,8 +148,8 @@
     ],
 
     data: [
-        "tests/elf32.xz",
-        "tests/elf64.xz",
+        "tests/files/elf32.xz",
+        "tests/files/elf64.xz",
     ],
 }
 
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 051f700..d7b483d 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -73,13 +73,15 @@
   return new MemoryRange(memory, start, end);
 }
 
-Elf* MapInfo::GetElf(pid_t pid, bool) {
+Elf* MapInfo::GetElf(pid_t pid, bool init_gnu_debugdata) {
   if (elf) {
     return elf;
   }
 
   elf = new Elf(CreateMemory(pid));
-  elf->Init();
+  if (elf->Init() && init_gnu_debugdata) {
+    elf->InitGnuDebugdata();
+  }
   // If the init fails, keep the elf around as an invalid object so we
   // don't try to reinit the object.
   return elf;
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 22cade2..bf0823b 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -24,6 +24,7 @@
 
 #include "Elf.h"
 
+#include "ElfTestUtils.h"
 #include "MemoryFake.h"
 
 #if !defined(PT_ARM_EXIDX)
@@ -36,36 +37,16 @@
     memory_ = new MemoryFake;
   }
 
-  template <typename Ehdr>
-  void InitEhdr(Ehdr* ehdr) {
-    memset(ehdr, 0, sizeof(Ehdr));
-    memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG);
-    ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
-    ehdr->e_ident[EI_VERSION] = EV_CURRENT;
-    ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
-
-    ehdr->e_type = ET_DYN;
-    ehdr->e_version = EV_CURRENT;
-  }
-
-  void InitElf32(uint32_t machine) {
+  void InitElf32(uint32_t machine_type) {
     Elf32_Ehdr ehdr;
+    TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, machine_type);
 
-    InitEhdr<Elf32_Ehdr>(&ehdr);
-    ehdr.e_ident[EI_CLASS] = ELFCLASS32;
-
-    ehdr.e_machine = machine;
-    ehdr.e_entry = 0;
     ehdr.e_phoff = 0x100;
-    ehdr.e_shoff = 0;
-    ehdr.e_flags = 0;
     ehdr.e_ehsize = sizeof(ehdr);
     ehdr.e_phentsize = sizeof(Elf32_Phdr);
     ehdr.e_phnum = 1;
     ehdr.e_shentsize = sizeof(Elf32_Shdr);
-    ehdr.e_shnum = 0;
-    ehdr.e_shstrndx = 0;
-    if (machine == EM_ARM) {
+    if (machine_type == EM_ARM) {
       ehdr.e_flags = 0x5000200;
       ehdr.e_phnum = 2;
     }
@@ -74,16 +55,13 @@
     Elf32_Phdr phdr;
     memset(&phdr, 0, sizeof(phdr));
     phdr.p_type = PT_LOAD;
-    phdr.p_offset = 0;
-    phdr.p_vaddr = 0;
-    phdr.p_paddr = 0;
     phdr.p_filesz = 0x10000;
     phdr.p_memsz = 0x10000;
     phdr.p_flags = PF_R | PF_X;
     phdr.p_align = 0x1000;
     memory_->SetMemory(0x100, &phdr, sizeof(phdr));
 
-    if (machine == EM_ARM) {
+    if (machine_type == EM_ARM) {
       memset(&phdr, 0, sizeof(phdr));
       phdr.p_type = PT_ARM_EXIDX;
       phdr.p_offset = 0x30000;
@@ -97,31 +75,21 @@
     }
   }
 
-  void InitElf64(uint32_t machine) {
+  void InitElf64(uint32_t machine_type) {
     Elf64_Ehdr ehdr;
+    TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, machine_type);
 
-    InitEhdr<Elf64_Ehdr>(&ehdr);
-    ehdr.e_ident[EI_CLASS] = ELFCLASS64;
-
-    ehdr.e_machine = machine;
-    ehdr.e_entry = 0;
     ehdr.e_phoff = 0x100;
-    ehdr.e_shoff = 0;
     ehdr.e_flags = 0x5000200;
     ehdr.e_ehsize = sizeof(ehdr);
     ehdr.e_phentsize = sizeof(Elf64_Phdr);
     ehdr.e_phnum = 1;
     ehdr.e_shentsize = sizeof(Elf64_Shdr);
-    ehdr.e_shnum = 0;
-    ehdr.e_shstrndx = 0;
     memory_->SetMemory(0, &ehdr, sizeof(ehdr));
 
     Elf64_Phdr phdr;
     memset(&phdr, 0, sizeof(phdr));
     phdr.p_type = PT_LOAD;
-    phdr.p_offset = 0;
-    phdr.p_vaddr = 0;
-    phdr.p_paddr = 0;
     phdr.p_filesz = 0x10000;
     phdr.p_memsz = 0x10000;
     phdr.p_flags = PF_R | PF_X;
@@ -129,12 +97,6 @@
     memory_->SetMemory(0x100, &phdr, sizeof(phdr));
   }
 
-  template <typename Ehdr, typename Shdr>
-  void GnuDebugdataInitFail(Ehdr* ehdr);
-
-  template <typename Ehdr, typename Shdr>
-  void GnuDebugdataInit(Ehdr* ehdr);
-
   MemoryFake* memory_;
 };
 
@@ -214,153 +176,64 @@
   ASSERT_TRUE(elf.interface() != nullptr);
 }
 
-template <typename Ehdr, typename Shdr>
-void ElfTest::GnuDebugdataInitFail(Ehdr* ehdr) {
+TEST_F(ElfTest, gnu_debugdata_init_fail32) {
+  TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
+                                               [&](uint64_t offset, const void* ptr, size_t size) {
+                                                 memory_->SetMemory(offset, ptr, size);
+                                               });
+
   Elf elf(memory_);
-
-  uint64_t offset = 0x2000;
-
-  ehdr->e_shoff = offset;
-  ehdr->e_shnum = 3;
-  ehdr->e_shentsize = sizeof(Shdr);
-  ehdr->e_shstrndx = 2;
-  memory_->SetMemory(0, ehdr, sizeof(*ehdr));
-
-  Shdr shdr;
-  memset(&shdr, 0, sizeof(shdr));
-  shdr.sh_type = SHT_NULL;
-  memory_->SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr->e_shentsize;
-
-  memset(&shdr, 0, sizeof(shdr));
-  shdr.sh_type = SHT_PROGBITS;
-  shdr.sh_name = 0x100;
-  shdr.sh_addr = 0x5000;
-  shdr.sh_offset = 0x5000;
-  shdr.sh_entsize = 0x100;
-  shdr.sh_size = 0x800;
-  memory_->SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr->e_shentsize;
-
-  memset(&shdr, 0, sizeof(shdr));
-  shdr.sh_type = SHT_STRTAB;
-  shdr.sh_name = 0x200000;
-  shdr.sh_offset = 0xf000;
-  shdr.sh_size = 0x1000;
-  memory_->SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr->e_shentsize;
-
-  memory_->SetMemory(0xf100, ".gnu_debugdata", sizeof(".gnu_debugdata"));
-
   ASSERT_TRUE(elf.Init());
   ASSERT_TRUE(elf.interface() != nullptr);
   ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
-  EXPECT_EQ(0x5000U, elf.interface()->gnu_debugdata_offset());
-  EXPECT_EQ(0x800U, elf.interface()->gnu_debugdata_size());
-
-  elf.InitGnuDebugdata();
-}
-
-TEST_F(ElfTest, gnu_debugdata_init_fail32) {
-  Elf32_Ehdr ehdr;
-  InitEhdr<Elf32_Ehdr>(&ehdr);
-  ehdr.e_ident[EI_CLASS] = ELFCLASS32;
-  ehdr.e_machine = EM_ARM;
-
-  GnuDebugdataInitFail<Elf32_Ehdr, Elf32_Shdr>(&ehdr);
+  EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
+  EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
 }
 
 TEST_F(ElfTest, gnu_debugdata_init_fail64) {
-  Elf64_Ehdr ehdr;
-  InitEhdr<Elf64_Ehdr>(&ehdr);
-  ehdr.e_ident[EI_CLASS] = ELFCLASS64;
-  ehdr.e_machine = EM_AARCH64;
+  TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
+                                               [&](uint64_t offset, const void* ptr, size_t size) {
+                                                 memory_->SetMemory(offset, ptr, size);
+                                               });
 
-  GnuDebugdataInitFail<Elf64_Ehdr, Elf64_Shdr>(&ehdr);
-}
-
-template <typename Ehdr, typename Shdr>
-void ElfTest::GnuDebugdataInit(Ehdr* ehdr) {
   Elf elf(memory_);
-
-  uint64_t offset = 0x2000;
-
-  ehdr->e_shoff = offset;
-  ehdr->e_shnum = 3;
-  ehdr->e_shentsize = sizeof(Shdr);
-  ehdr->e_shstrndx = 2;
-  memory_->SetMemory(0, ehdr, sizeof(*ehdr));
-
-  Shdr shdr;
-  memset(&shdr, 0, sizeof(shdr));
-  shdr.sh_type = SHT_NULL;
-  memory_->SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr->e_shentsize;
-
-  uint64_t gnu_offset = offset;
-  offset += ehdr->e_shentsize;
-
-  memset(&shdr, 0, sizeof(shdr));
-  shdr.sh_type = SHT_STRTAB;
-  shdr.sh_name = 0x200000;
-  shdr.sh_offset = 0xf000;
-  shdr.sh_size = 0x1000;
-  memory_->SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr->e_shentsize;
-
-  memory_->SetMemory(0xf100, ".gnu_debugdata", sizeof(".gnu_debugdata"));
-
-  // Read in the compressed elf data and put it in our fake memory.
-  std::string name("tests/");
-  if (sizeof(Ehdr) == sizeof(Elf32_Ehdr)) {
-    name += "elf32.xz";
-  } else {
-    name += "elf64.xz";
-  }
-  int fd = TEMP_FAILURE_RETRY(open(name.c_str(), O_RDONLY));
-  ASSERT_NE(-1, fd) << "Cannot open " + name;
-  // Assumes the file is less than 1024 bytes.
-  std::vector<uint8_t> buf(1024);
-  ssize_t bytes = TEMP_FAILURE_RETRY(read(fd, buf.data(), buf.size()));
-  ASSERT_GT(bytes, 0);
-  // Make sure the file isn't too big.
-  ASSERT_NE(static_cast<size_t>(bytes), buf.size())
-      << "File " + name + " is too big, increase buffer size.";
-  close(fd);
-  buf.resize(bytes);
-  memory_->SetMemory(0x5000, buf);
-
-  memset(&shdr, 0, sizeof(shdr));
-  shdr.sh_type = SHT_PROGBITS;
-  shdr.sh_name = 0x100;
-  shdr.sh_addr = 0x5000;
-  shdr.sh_offset = 0x5000;
-  shdr.sh_size = bytes;
-  memory_->SetMemory(gnu_offset, &shdr, sizeof(shdr));
-
   ASSERT_TRUE(elf.Init());
   ASSERT_TRUE(elf.interface() != nullptr);
   ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
-  EXPECT_EQ(0x5000U, elf.interface()->gnu_debugdata_offset());
+  EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
+  EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
+}
+
+TEST_F(ElfTest, gnu_debugdata_init32) {
+  TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
+                                               [&](uint64_t offset, const void* ptr, size_t size) {
+                                                 memory_->SetMemory(offset, ptr, size);
+                                               });
+
+  Elf elf(memory_);
+  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.interface() != nullptr);
+  ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
+  EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
+  EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size());
 
   elf.InitGnuDebugdata();
   ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
 }
 
-TEST_F(ElfTest, gnu_debugdata_init32) {
-  Elf32_Ehdr ehdr;
-  InitEhdr<Elf32_Ehdr>(&ehdr);
-  ehdr.e_ident[EI_CLASS] = ELFCLASS32;
-  ehdr.e_machine = EM_ARM;
-
-  GnuDebugdataInit<Elf32_Ehdr, Elf32_Shdr>(&ehdr);
-}
-
 TEST_F(ElfTest, gnu_debugdata_init64) {
-  Elf64_Ehdr ehdr;
-  InitEhdr<Elf64_Ehdr>(&ehdr);
-  ehdr.e_ident[EI_CLASS] = ELFCLASS64;
-  ehdr.e_machine = EM_AARCH64;
+  TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
+                                               [&](uint64_t offset, const void* ptr, size_t size) {
+                                                 memory_->SetMemory(offset, ptr, size);
+                                               });
 
-  GnuDebugdataInit<Elf64_Ehdr, Elf64_Shdr>(&ehdr);
+  Elf elf(memory_);
+  ASSERT_TRUE(elf.Init());
+  ASSERT_TRUE(elf.interface() != nullptr);
+  ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
+  EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
+  EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size());
+
+  elf.InitGnuDebugdata();
+  ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
 }
diff --git a/libunwindstack/tests/ElfTestUtils.cpp b/libunwindstack/tests/ElfTestUtils.cpp
new file mode 100644
index 0000000..8755f16
--- /dev/null
+++ b/libunwindstack/tests/ElfTestUtils.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "ElfTestUtils.h"
+
+template <typename Ehdr>
+void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type) {
+  memset(ehdr, 0, sizeof(Ehdr));
+  memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG);
+  ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
+  ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+  ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
+  ehdr->e_ident[EI_CLASS] = elf_class;
+  ehdr->e_type = ET_DYN;
+  ehdr->e_machine = machine_type;
+  ehdr->e_version = EV_CURRENT;
+  ehdr->e_ehsize = sizeof(Ehdr);
+}
+
+template <typename Ehdr, typename Shdr>
+void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine, bool init_gnu_debugdata,
+                          TestCopyFuncType copy_func) {
+  Ehdr ehdr;
+
+  TestInitEhdr(&ehdr, elf_class, machine);
+
+  uint64_t offset = sizeof(Ehdr);
+  ehdr.e_shoff = offset;
+  ehdr.e_shnum = 3;
+  ehdr.e_shentsize = sizeof(Shdr);
+  ehdr.e_shstrndx = 2;
+  copy_func(0, &ehdr, sizeof(ehdr));
+
+  Shdr shdr;
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_NULL;
+  copy_func(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  // Skip this header, it will contain the gnu_debugdata information.
+  uint64_t gnu_offset = offset;
+  offset += ehdr.e_shentsize;
+
+  uint64_t symtab_offset = sizeof(ehdr) + ehdr.e_shnum * ehdr.e_shentsize;
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_name = 1;
+  shdr.sh_type = SHT_STRTAB;
+  shdr.sh_offset = symtab_offset;
+  shdr.sh_size = 0x100;
+  copy_func(offset, &shdr, sizeof(shdr));
+
+  char value = '\0';
+  uint64_t symname_offset = symtab_offset;
+  copy_func(symname_offset, &value, 1);
+  symname_offset++;
+  std::string name(".shstrtab");
+  copy_func(symname_offset, name.c_str(), name.size() + 1);
+  symname_offset += name.size() + 1;
+  name = ".gnu_debugdata";
+  copy_func(symname_offset, name.c_str(), name.size() + 1);
+
+  ssize_t bytes = 0x100;
+  offset = symtab_offset + 0x100;
+  if (init_gnu_debugdata) {
+    // Read in the compressed elf data and copy it in.
+    name = "tests/files/";
+    if (elf_class == ELFCLASS32) {
+      name += "elf32.xz";
+    } else {
+      name += "elf64.xz";
+    }
+    int fd = TEMP_FAILURE_RETRY(open(name.c_str(), O_RDONLY));
+    ASSERT_NE(-1, fd) << "Cannot open " + name;
+    // Assumes the file is less than 1024 bytes.
+    std::vector<uint8_t> buf(1024);
+    bytes = TEMP_FAILURE_RETRY(read(fd, buf.data(), buf.size()));
+    ASSERT_GT(bytes, 0);
+    // Make sure the file isn't too big.
+    ASSERT_NE(static_cast<size_t>(bytes), buf.size())
+        << "File " + name + " is too big, increase buffer size.";
+    close(fd);
+    buf.resize(bytes);
+    copy_func(offset, buf.data(), buf.size());
+  }
+
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_name = symname_offset - symtab_offset;
+  shdr.sh_addr = offset;
+  shdr.sh_offset = offset;
+  shdr.sh_size = bytes;
+  copy_func(gnu_offset, &shdr, sizeof(shdr));
+}
+
+template void TestInitEhdr<Elf32_Ehdr>(Elf32_Ehdr*, uint32_t, uint32_t);
+template void TestInitEhdr<Elf64_Ehdr>(Elf64_Ehdr*, uint32_t, uint32_t);
+
+template void TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(uint32_t, uint32_t, bool,
+                                                           TestCopyFuncType);
+template void TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(uint32_t, uint32_t, bool,
+                                                           TestCopyFuncType);
diff --git a/libunwindstack/tests/ElfTestUtils.h b/libunwindstack/tests/ElfTestUtils.h
new file mode 100644
index 0000000..4fd3bbc
--- /dev/null
+++ b/libunwindstack/tests/ElfTestUtils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
+#define _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
+
+#include <functional>
+
+typedef std::function<void(uint64_t, const void*, size_t)> TestCopyFuncType;
+
+template <typename Ehdr>
+void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type);
+
+template <typename Ehdr, typename Shdr>
+void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine_type, bool init_gnu_debudata,
+                          TestCopyFuncType copy_func);
+
+#endif  // _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
similarity index 85%
rename from libunwindstack/tests/MapInfoTest.cpp
rename to libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index 6e47dc0..d7433e1 100644
--- a/libunwindstack/tests/MapInfoTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -34,7 +34,7 @@
 #include "MapInfo.h"
 #include "Memory.h"
 
-class MapInfoTest : public ::testing::Test {
+class MapInfoCreateMemoryTest : public ::testing::Test {
  protected:
   static void SetUpTestCase() {
     std::vector<uint8_t> buffer(1024);
@@ -58,10 +58,10 @@
 
   static TemporaryFile elf_at_100_;
 };
-TemporaryFile MapInfoTest::elf_;
-TemporaryFile MapInfoTest::elf_at_100_;
+TemporaryFile MapInfoCreateMemoryTest::elf_;
+TemporaryFile MapInfoCreateMemoryTest::elf_at_100_;
 
-TEST_F(MapInfoTest, end_le_start) {
+TEST_F(MapInfoCreateMemoryTest, end_le_start) {
   MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path};
 
   std::unique_ptr<Memory> memory;
@@ -80,7 +80,7 @@
 
 // Verify that if the offset is non-zero but there is no elf at the offset,
 // that the full file is used.
-TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_full_file) {
+TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
   MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_.path};
 
   std::unique_ptr<Memory> memory(info.CreateMemory(getpid()));
@@ -100,7 +100,7 @@
 
 // Verify that if the offset is non-zero and there is an elf at that
 // offset, that only part of the file is used.
-TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_partial_file) {
+TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
   MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_at_100_.path};
 
   std::unique_ptr<Memory> memory(info.CreateMemory(getpid()));
@@ -119,7 +119,7 @@
 }
 
 // Verify that device file names will never result in Memory object creation.
-TEST_F(MapInfoTest, create_memory_check_device_maps) {
+TEST_F(MapInfoCreateMemoryTest, check_device_maps) {
   // Set up some memory so that a valid local memory object would
   // be returned if the file mapping fails, but the device check is incorrect.
   std::vector<uint8_t> buffer(1024);
@@ -135,7 +135,7 @@
   ASSERT_TRUE(memory.get() == nullptr);
 }
 
-TEST_F(MapInfoTest, create_memory_local_memory) {
+TEST_F(MapInfoCreateMemoryTest, local_memory) {
   // Set up some memory for a valid local memory object.
   std::vector<uint8_t> buffer(1024);
   for (size_t i = 0; i < buffer.size(); i++) {
@@ -160,7 +160,7 @@
   ASSERT_FALSE(memory->Read(read_buffer.size(), read_buffer.data(), 1));
 }
 
-TEST_F(MapInfoTest, create_memory_remote_memory) {
+TEST_F(MapInfoCreateMemoryTest, remote_memory) {
   std::vector<uint8_t> buffer(1024);
   memset(buffer.data(), 0xa, buffer.size());
 
@@ -202,19 +202,3 @@
 
   kill(pid, SIGKILL);
 }
-
-TEST_F(MapInfoTest, get_elf) {
-  // Create a map to use as initialization data.
-  void* map = mmap(nullptr, 1024, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  ASSERT_NE(MAP_FAILED, map);
-
-  uint64_t start = reinterpret_cast<uint64_t>(map);
-  MapInfo info{.start = start, .end = start + 1024, .offset = 0, .name = ""};
-
-  // The map contains garbage, but this should still produce an elf object.
-  std::unique_ptr<Elf> elf(info.GetElf(getpid(), false));
-  ASSERT_TRUE(elf.get() != nullptr);
-  ASSERT_FALSE(elf->valid());
-
-  ASSERT_EQ(0, munmap(map, 1024));
-}
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
new file mode 100644
index 0000000..fc36cc6
--- /dev/null
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <elf.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <memory>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/test_utils.h>
+#include <gtest/gtest.h>
+
+#include "Elf.h"
+#include "ElfTestUtils.h"
+#include "MapInfo.h"
+
+class MapInfoGetElfTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    map_ = mmap(nullptr, kMapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    ASSERT_NE(MAP_FAILED, map_);
+
+    uint64_t start = reinterpret_cast<uint64_t>(map_);
+    info_.reset(new MapInfo{.start = start, .end = start + 1024, .offset = 0, .name = ""});
+  }
+
+  void TearDown() override { munmap(map_, kMapSize); }
+
+  const size_t kMapSize = 4096;
+
+  void* map_ = nullptr;
+  std::unique_ptr<MapInfo> info_;
+};
+
+TEST_F(MapInfoGetElfTest, invalid) {
+  // The map is empty, but this should still create an invalid elf object.
+  std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false));
+  ASSERT_TRUE(elf.get() != nullptr);
+  ASSERT_FALSE(elf->valid());
+}
+
+TEST_F(MapInfoGetElfTest, valid32) {
+  Elf32_Ehdr ehdr;
+  TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+  memcpy(map_, &ehdr, sizeof(ehdr));
+
+  std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false));
+  ASSERT_TRUE(elf.get() != nullptr);
+  ASSERT_TRUE(elf->valid());
+  EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
+  EXPECT_EQ(ELFCLASS32, elf->class_type());
+}
+
+TEST_F(MapInfoGetElfTest, valid64) {
+  Elf64_Ehdr ehdr;
+  TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
+  memcpy(map_, &ehdr, sizeof(ehdr));
+
+  std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false));
+  ASSERT_TRUE(elf.get() != nullptr);
+  ASSERT_TRUE(elf->valid());
+  EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
+  EXPECT_EQ(ELFCLASS64, elf->class_type());
+}
+
+TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
+  TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(
+      ELFCLASS32, EM_ARM, false, [&](uint64_t offset, const void* ptr, size_t size) {
+        memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size);
+      });
+
+  std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false));
+  ASSERT_TRUE(elf.get() != nullptr);
+  ASSERT_TRUE(elf->valid());
+  EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
+  EXPECT_EQ(ELFCLASS32, elf->class_type());
+  EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
+}
+
+TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
+  TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(
+      ELFCLASS64, EM_AARCH64, false, [&](uint64_t offset, const void* ptr, size_t size) {
+        memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size);
+      });
+
+  std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false));
+  ASSERT_TRUE(elf.get() != nullptr);
+  ASSERT_TRUE(elf->valid());
+  EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
+  EXPECT_EQ(ELFCLASS64, elf->class_type());
+  EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
+}
+
+TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
+  TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(
+      ELFCLASS32, EM_ARM, true, [&](uint64_t offset, const void* ptr, size_t size) {
+        memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size);
+      });
+
+  std::unique_ptr<Elf> elf(info_->GetElf(getpid(), true));
+  ASSERT_TRUE(elf.get() != nullptr);
+  ASSERT_TRUE(elf->valid());
+  EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
+  EXPECT_EQ(ELFCLASS32, elf->class_type());
+  EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
+}
+
+TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
+  TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(
+      ELFCLASS64, EM_AARCH64, true, [&](uint64_t offset, const void* ptr, size_t size) {
+        memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size);
+      });
+
+  std::unique_ptr<Elf> elf(info_->GetElf(getpid(), true));
+  ASSERT_TRUE(elf.get() != nullptr);
+  ASSERT_TRUE(elf->valid());
+  EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
+  EXPECT_EQ(ELFCLASS64, elf->class_type());
+  EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
+}
diff --git a/libunwindstack/tests/elf32.xz b/libunwindstack/tests/files/elf32.xz
similarity index 100%
rename from libunwindstack/tests/elf32.xz
rename to libunwindstack/tests/files/elf32.xz
Binary files differ
diff --git a/libunwindstack/tests/elf64.xz b/libunwindstack/tests/files/elf64.xz
similarity index 100%
rename from libunwindstack/tests/elf64.xz
rename to libunwindstack/tests/files/elf64.xz
Binary files differ
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3893722..84d0f87 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -36,8 +36,6 @@
     mount cgroup none /dev/memcg memory
     # app mem cgroups, used by activity manager, lmkd and zygote
     mkdir /dev/memcg/apps/ 0755 system system
-    # cgroup for system_server and surfaceflinger
-    mkdir /dev/memcg/system 0755 system system
 
     start ueventd
 
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 6d35fed..9620d63 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -4,7 +4,6 @@
         "bzip2",
         "grep",
         "grep_vendor",
-        "gzip",
         "mkshrc",
         "mkshrc_vendor",
         "reboot",