Merge "Modernize codebase by replacing NULL with nullptr"
diff --git a/base/file.cpp b/base/file.cpp
index 2f697a1..d6fe753 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -199,17 +199,23 @@
 bool RemoveFileIfExists(const std::string& path, std::string* err) {
   struct stat st;
 #if defined(_WIN32)
-  //TODO: Windows version can't handle symbol link correctly.
+  // TODO: Windows version can't handle symbolic links correctly.
   int result = stat(path.c_str(), &st);
   bool file_type_removable = (result == 0 && S_ISREG(st.st_mode));
 #else
   int result = lstat(path.c_str(), &st);
   bool file_type_removable = (result == 0 && (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)));
 #endif
+  if (result == -1) {
+    if (errno == ENOENT || errno == ENOTDIR) return true;
+    if (err != nullptr) *err = strerror(errno);
+    return false;
+  }
+
   if (result == 0) {
     if (!file_type_removable) {
       if (err != nullptr) {
-        *err = "is not a regular or symbol link file";
+        *err = "is not a regular file or symbolic link";
       }
       return false;
     }
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 02b431d..6794652 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -26,6 +26,10 @@
 
 #include "android-base/test_utils.h"
 
+#if !defined(_WIN32)
+#include <pwd.h>
+#endif
+
 TEST(file, ReadFileToString_ENOENT) {
   std::string s("hello");
   errno = 0;
@@ -115,7 +119,7 @@
   ASSERT_FALSE(android::base::ReadFully(tf.fd, &s[0], s.size()));
 }
 
-TEST(file, RemoveFileIfExist) {
+TEST(file, RemoveFileIfExists) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
   close(tf.fd);
@@ -126,9 +130,43 @@
   TemporaryDir td;
   ASSERT_FALSE(android::base::RemoveFileIfExists(td.path));
   ASSERT_FALSE(android::base::RemoveFileIfExists(td.path, &err));
-  ASSERT_EQ("is not a regular or symbol link file", err);
+  ASSERT_EQ("is not a regular file or symbolic link", err);
 }
 
+TEST(file, RemoveFileIfExists_ENOTDIR) {
+  TemporaryFile tf;
+  close(tf.fd);
+  tf.fd = -1;
+  std::string err{"xxx"};
+  ASSERT_TRUE(android::base::RemoveFileIfExists(std::string{tf.path} + "/abc", &err));
+  ASSERT_EQ("xxx", err);
+}
+
+#if !defined(_WIN32)
+TEST(file, RemoveFileIfExists_EACCES) {
+  // EACCES -- one of the directories in the path has no search permission
+  // root can bypass permission restrictions, so drop root.
+  if (getuid() == 0) {
+    passwd* shell = getpwnam("shell");
+    setgid(shell->pw_gid);
+    setuid(shell->pw_uid);
+  }
+
+  TemporaryDir td;
+  TemporaryFile tf(td.path);
+  close(tf.fd);
+  tf.fd = -1;
+  std::string err{"xxx"};
+  // Remove dir's search permission.
+  ASSERT_TRUE(chmod(td.path, S_IRUSR | S_IWUSR) == 0);
+  ASSERT_FALSE(android::base::RemoveFileIfExists(tf.path, &err));
+  ASSERT_EQ("Permission denied", err);
+  // Set dir's search permission again.
+  ASSERT_TRUE(chmod(td.path, S_IRWXU) == 0);
+  ASSERT_TRUE(android::base::RemoveFileIfExists(tf.path, &err));
+}
+#endif
+
 TEST(file, Readlink) {
 #if !defined(_WIN32)
   // Linux doesn't allow empty symbolic links.
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 720590d..d15fa8c 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -27,8 +27,8 @@
 #include <android-base/unique_fd.h>
 #include <uuid/uuid.h>
 
-#include "liblp/metadata_format.h"
-#include "liblp/reader.h"
+#include "liblp/liblp.h"
+#include "reader.h"
 #include "utility.h"
 
 namespace android {
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 3cd95ae..8bde313 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -23,7 +23,7 @@
 #include <map>
 #include <memory>
 
-#include "metadata_format.h"
+#include "liblp.h"
 
 namespace android {
 namespace fs_mgr {
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
new file mode 100644
index 0000000..469ef9e
--- /dev/null
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -0,0 +1,75 @@
+//
+// Copyright (C) 2018 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 LIBLP_LIBLP_H
+#define LIBLP_LIBLP_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "metadata_format.h"
+
+namespace android {
+namespace fs_mgr {
+
+// Helper structure for easily interpreting deserialized metadata, or
+// re-serializing metadata.
+struct LpMetadata {
+    LpMetadataGeometry geometry;
+    LpMetadataHeader header;
+    std::vector<LpMetadataPartition> partitions;
+    std::vector<LpMetadataExtent> extents;
+};
+
+// Place an initial partition table on the device. This will overwrite the
+// existing geometry, and should not be used for normal partition table
+// updates. False can be returned if the geometry is incompatible with the
+// block device or an I/O error occurs.
+bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata,
+                         uint32_t slot_number);
+
+// Update the partition table for a given metadata slot number. False is
+// returned if an error occurs, which can include:
+//  - Invalid slot number.
+//  - I/O error.
+//  - Corrupt or missing metadata geometry on disk.
+//  - Incompatible geometry.
+bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
+                          uint32_t slot_number);
+
+// Read logical partition metadata from its predetermined location on a block
+// device. If readback fails, we also attempt to load from a backup copy.
+std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number);
+
+// Read/Write logical partition metadata to an image file, for diagnostics or
+// flashing.
+bool WriteToImageFile(const char* file, const LpMetadata& metadata);
+std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file);
+
+// Helper to extract safe C++ strings from partition info.
+std::string GetPartitionName(const LpMetadataPartition& partition);
+std::string GetPartitionGuid(const LpMetadataPartition& partition);
+
+// Helper to return a slot number for a slot suffix.
+uint32_t SlotNumberForSlotSuffix(const std::string& suffix);
+
+}  // namespace fs_mgr
+}  // namespace android
+
+#endif  // LIBLP_LIBLP_H
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 27602ac..b5202f0 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -67,7 +67,7 @@
  *     | Geometry Backup    |
  *     +--------------------+
  */
-#define LP_METADATA_PARTITION_NAME "android"
+#define LP_METADATA_PARTITION_NAME "super"
 
 /* Size of a sector is always 512 bytes for compatibility with the Linux kernel. */
 #define LP_SECTOR_SIZE 512
@@ -262,28 +262,4 @@
 } /* extern "C" */
 #endif
 
-#ifdef __cplusplus
-namespace android {
-namespace fs_mgr {
-
-// Helper structure for easily interpreting deserialized metadata, or
-// re-serializing metadata.
-struct LpMetadata {
-    LpMetadataGeometry geometry;
-    LpMetadataHeader header;
-    std::vector<LpMetadataPartition> partitions;
-    std::vector<LpMetadataExtent> extents;
-};
-
-// Helper to extract safe C++ strings from partition info.
-std::string GetPartitionName(const LpMetadataPartition& partition);
-std::string GetPartitionGuid(const LpMetadataPartition& partition);
-
-// Helper to return a slot number for a slot suffix.
-uint32_t SlotNumberForSlotSuffix(const std::string& suffix);
-
-}  // namespace fs_mgr
-}  // namespace android
-#endif
-
 #endif /* LOGICAL_PARTITION_METADATA_FORMAT_H_ */
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index de10eb6..e91cc3e 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -23,10 +23,10 @@
 #include <android-base/unique_fd.h>
 #include <gtest/gtest.h>
 #include <liblp/builder.h>
-#include <liblp/reader.h>
-#include <liblp/writer.h>
 
+#include "reader.h"
 #include "utility.h"
+#include "writer.h"
 
 using namespace std;
 using namespace android::fs_mgr;
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index d680baf..985cf09 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "liblp/reader.h"
+#include "reader.h"
 
 #include <stddef.h>
 #include <stdlib.h>
@@ -165,8 +165,6 @@
     return true;
 }
 
-using ReadMetadataFn = std::function<bool(void* buffer, size_t num_bytes)>;
-
 // Parse and validate all metadata at the current position in the given file
 // descriptor.
 static std::unique_ptr<LpMetadata> ParseMetadata(int fd) {
diff --git a/fs_mgr/liblp/include/liblp/reader.h b/fs_mgr/liblp/reader.h
similarity index 77%
rename from fs_mgr/liblp/include/liblp/reader.h
rename to fs_mgr/liblp/reader.h
index 9f01441..c4cac8f 100644
--- a/fs_mgr/liblp/include/liblp/reader.h
+++ b/fs_mgr/liblp/reader.h
@@ -21,14 +21,11 @@
 
 #include <memory>
 
-#include "metadata_format.h"
+#include <liblp/liblp.h>
 
 namespace android {
 namespace fs_mgr {
 
-// Read logical partition metadata from its predetermined location on a block
-// device. If readback fails, we also attempt to load from a backup copy.
-std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number);
 std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number);
 
 // Helper functions for manually reading geometry and metadata.
@@ -40,9 +37,6 @@
 std::unique_ptr<LpMetadata> ReadBackupMetadata(int fd, const LpMetadataGeometry& geometry,
                                                uint32_t slot_number);
 
-// Read logical partition metadata from an image file that was created with
-// WriteToImageFile().
-std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file);
 std::unique_ptr<LpMetadata> ReadFromImageFile(int fd);
 
 }  // namespace fs_mgr
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index dcc569e..2143e13 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-#include "utility.h"
 #include <gtest/gtest.h>
+#include <liblp/liblp.h>
+
+#include "utility.h"
 
 using namespace android;
 using namespace android::fs_mgr;
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 963974c..b85e4ad 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "writer.h"
+
 #include <inttypes.h>
 #include <unistd.h>
 
@@ -22,8 +24,7 @@
 #include <android-base/file.h>
 #include <android-base/unique_fd.h>
 
-#include "liblp/reader.h"
-#include "liblp/writer.h"
+#include "reader.h"
 #include "utility.h"
 
 namespace android {
diff --git a/fs_mgr/liblp/include/liblp/writer.h b/fs_mgr/liblp/writer.h
similarity index 65%
rename from fs_mgr/liblp/include/liblp/writer.h
rename to fs_mgr/liblp/writer.h
index da38a4c..94c1d31 100644
--- a/fs_mgr/liblp/include/liblp/writer.h
+++ b/fs_mgr/liblp/writer.h
@@ -18,27 +18,13 @@
 #define LIBLP_WRITER_H
 
 #include <functional>
-#include "metadata_format.h"
+#include <string>
+
+#include <liblp/liblp.h>
 
 namespace android {
 namespace fs_mgr {
 
-// Place an initial partition table on the device. This will overwrite the
-// existing geometry, and should not be used for normal partition table
-// updates. False can be returned if the geometry is incompatible with the
-// block device or an I/O error occurs.
-bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata,
-                         uint32_t slot_number);
-
-// Update the partition table for a given metadata slot number. False is
-// returned if an error occurs, which can include:
-//  - Invalid slot number.
-//  - I/O error.
-//  - Corrupt or missing metadata geometry on disk.
-//  - Incompatible geometry.
-bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
-                          uint32_t slot_number);
-
 // These variants are for testing only. The path-based functions should be used
 // for actual operation, so that open() is called with the correct flags.
 bool FlashPartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number);
diff --git a/init/service.cpp b/init/service.cpp
index 95b37ab..4c2747e 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -130,7 +130,7 @@
         if (umount2("/sys", MNT_DETACH) == -1) {
             return ErrnoError() << "Could not umount(/sys)";
         }
-        if (mount("", "/sys", "sys", kSafeFlags, "") == -1) {
+        if (mount("", "/sys", "sysfs", kSafeFlags, "") == -1) {
             return ErrnoError() << "Could not mount(/sys)";
         }
     }
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 58e59d6..37afb98 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -20,6 +20,7 @@
 libcutils_nonwindows_sources = [
     "android_get_control_file.cpp",
     "fs.cpp",
+    "hashmap.cpp",
     "multiuser.cpp",
     "socket_inaddr_any_server_unix.cpp",
     "socket_local_client_unix.cpp",
@@ -61,7 +62,6 @@
         "config_utils.cpp",
         "fs_config.cpp",
         "canned_fs_config.cpp",
-        "hashmap.cpp",
         "iosched_policy.cpp",
         "load_file.cpp",
         "native_handle.cpp",
diff --git a/libcutils/hashmap.cpp b/libcutils/hashmap.cpp
index 2a4a52e..57d6006 100644
--- a/libcutils/hashmap.cpp
+++ b/libcutils/hashmap.cpp
@@ -18,7 +18,7 @@
 
 #include <assert.h>
 #include <errno.h>
-#include <cutils/threads.h>
+#include <pthread.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
@@ -36,7 +36,7 @@
     size_t bucketCount;
     int (*hash)(void* key);
     bool (*equals)(void* keyA, void* keyB);
-    mutex_t lock;
+    pthread_mutex_t lock;
     size_t size;
 };
 
@@ -69,7 +69,7 @@
     map->hash = hash;
     map->equals = equals;
 
-    mutex_init(&map->lock);
+    pthread_mutex_init(&map->lock, nullptr);
 
     return map;
 }
@@ -129,11 +129,11 @@
 }
 
 void hashmapLock(Hashmap* map) {
-    mutex_lock(&map->lock);
+    pthread_mutex_lock(&map->lock);
 }
 
 void hashmapUnlock(Hashmap* map) {
-    mutex_unlock(&map->lock);
+    pthread_mutex_unlock(&map->lock);
 }
 
 void hashmapFree(Hashmap* map) {
@@ -147,7 +147,7 @@
         }
     }
     free(map->buckets);
-    mutex_destroy(&map->lock);
+    pthread_mutex_destroy(&map->lock);
     free(map);
 }
 
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 915cddb..2c00456 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -204,49 +204,19 @@
   uint64_t offset = ehdr.e_phoff;
   for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
     PhdrType phdr;
-    if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) {
+    if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
       last_error_.code = ERROR_MEMORY_INVALID;
-      last_error_.address =
-          offset + reinterpret_cast<uintptr_t>(&phdr.p_type) - reinterpret_cast<uintptr_t>(&phdr);
+      last_error_.address = offset;
       return false;
     }
 
-    if (HandleType(offset, phdr.p_type)) {
-      continue;
-    }
-
     switch (phdr.p_type) {
     case PT_LOAD:
     {
-      // Get the flags first, if this isn't an executable header, ignore it.
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_flags) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
       if ((phdr.p_flags & PF_X) == 0) {
         continue;
       }
 
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
       pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
                                           static_cast<size_t>(phdr.p_memsz)};
       if (phdr.p_offset == 0) {
@@ -256,46 +226,20 @@
     }
 
     case PT_GNU_EH_FRAME:
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
       // This is really the pointer to the .eh_frame_hdr section.
       eh_frame_hdr_offset_ = phdr.p_offset;
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
       eh_frame_hdr_size_ = phdr.p_memsz;
       break;
 
     case PT_DYNAMIC:
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
       dynamic_offset_ = phdr.p_offset;
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
       dynamic_vaddr_ = phdr.p_vaddr;
-      if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
-        last_error_.code = ERROR_MEMORY_INVALID;
-        last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
-                              reinterpret_cast<uintptr_t>(&phdr);
-        return false;
-      }
       dynamic_size_ = phdr.p_memsz;
       break;
+
+    default:
+      HandleUnknownType(phdr.p_type, phdr.p_offset, phdr.p_filesz);
+      break;
     }
   }
   return true;
@@ -313,8 +257,7 @@
   ShdrType shdr;
   if (ehdr.e_shstrndx < ehdr.e_shnum) {
     uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
-    if (memory_->ReadField(sh_offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
-        memory_->ReadField(sh_offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
+    if (memory_->ReadFully(sh_offset, &shdr, sizeof(shdr))) {
       sec_offset = shdr.sh_offset;
       sec_size = shdr.sh_size;
     }
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index a3244e8..3dd5d54 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -87,23 +87,17 @@
 #define PT_ARM_EXIDX 0x70000001
 #endif
 
-bool ElfInterfaceArm::HandleType(uint64_t offset, uint32_t type) {
+void ElfInterfaceArm::HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) {
   if (type != PT_ARM_EXIDX) {
-    return false;
-  }
-
-  Elf32_Phdr phdr;
-  if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
-    return true;
+    return;
   }
 
   // The offset already takes into account the load bias.
-  start_offset_ = phdr.p_offset;
+  start_offset_ = ph_offset;
 
   // Always use filesz instead of memsz. In most cases they are the same,
   // but some shared libraries wind up setting one correctly and not the other.
-  total_entries_ = phdr.p_filesz / 8;
-  return true;
+  total_entries_ = ph_filesz / 8;
 }
 
 bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h
index 3bee9cf..4c3a0c3 100644
--- a/libunwindstack/ElfInterfaceArm.h
+++ b/libunwindstack/ElfInterfaceArm.h
@@ -70,7 +70,7 @@
 
   bool FindEntry(uint32_t pc, uint64_t* entry_offset);
 
-  bool HandleType(uint64_t offset, uint32_t type) override;
+  void HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) override;
 
   bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) override;
 
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index 0c588da..5c1210d 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -118,7 +118,7 @@
   template <typename SymType>
   bool GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address);
 
-  virtual bool HandleType(uint64_t, uint32_t) { return false; }
+  virtual void HandleUnknownType(uint32_t, uint64_t, uint64_t) {}
 
   template <typename EhdrType>
   static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size);
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index c0c07f4..dee5e98 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -41,18 +41,6 @@
 
   bool ReadFully(uint64_t addr, void* dst, size_t size);
 
-  inline bool ReadField(uint64_t addr, void* start, void* field, size_t size) {
-    if (reinterpret_cast<uintptr_t>(field) < reinterpret_cast<uintptr_t>(start)) {
-      return false;
-    }
-    uint64_t offset = reinterpret_cast<uintptr_t>(field) - reinterpret_cast<uintptr_t>(start);
-    if (__builtin_add_overflow(addr, offset, &offset)) {
-      return false;
-    }
-    // The read will check if offset + size overflows.
-    return ReadFully(offset, field, size);
-  }
-
   inline bool Read32(uint64_t addr, uint32_t* dst) {
     return ReadFully(addr, dst, sizeof(uint32_t));
   }
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index a8bb4aa..43c6a97 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -242,44 +242,21 @@
   ASSERT_EQ(0xa020U, entries[4]);
 }
 
-TEST_F(ElfInterfaceArmTest, HandleType_not_arm_exidx) {
+TEST_F(ElfInterfaceArmTest, HandleUnknownType_arm_exidx) {
   ElfInterfaceArmFake interface(&memory_);
 
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_NULL));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOAD));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_DYNAMIC));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_INTERP));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_NOTE));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_SHLIB));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_PHDR));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_TLS));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOOS));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIOS));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_LOPROC));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_HIPROC));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_EH_FRAME));
-  ASSERT_FALSE(interface.HandleType(0x1000, PT_GNU_STACK));
-}
-
-TEST_F(ElfInterfaceArmTest, HandleType_arm_exidx) {
-  ElfInterfaceArmFake interface(&memory_);
-
-  Elf32_Phdr phdr = {};
   interface.FakeSetStartOffset(0x1000);
   interface.FakeSetTotalEntries(100);
-  phdr.p_offset = 0x2000;
-  phdr.p_filesz = 0xa00;
 
-  // Verify that if reads fail, we don't set the values but still get true.
-  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
+  // Verify that if the type is not the one we want, we don't set the values.
+  interface.HandleUnknownType(0x70000000, 0x2000, 320);
   ASSERT_EQ(0x1000U, interface.start_offset());
   ASSERT_EQ(100U, interface.total_entries());
 
   // Everything is correct and present.
-  memory_.SetMemory(0x1000, &phdr, sizeof(phdr));
-  ASSERT_TRUE(interface.HandleType(0x1000, 0x70000001));
+  interface.HandleUnknownType(0x70000001, 0x2000, 320);
   ASSERT_EQ(0x2000U, interface.start_offset());
-  ASSERT_EQ(320U, interface.total_entries());
+  ASSERT_EQ(40U, interface.total_entries());
 }
 
 TEST_F(ElfInterfaceArmTest, StepExidx) {
diff --git a/libunwindstack/tests/MemoryTest.cpp b/libunwindstack/tests/MemoryTest.cpp
index 4a9ed9f..3655984 100644
--- a/libunwindstack/tests/MemoryTest.cpp
+++ b/libunwindstack/tests/MemoryTest.cpp
@@ -51,40 +51,6 @@
   uint64_t four;
 };
 
-TEST(MemoryTest, read_field) {
-  MemoryFakeAlwaysReadZero memory;
-
-  FakeStruct data;
-  memset(&data, 0xff, sizeof(data));
-  ASSERT_TRUE(memory.ReadField(0, &data, &data.one, sizeof(data.one)));
-  ASSERT_EQ(0, data.one);
-
-  memset(&data, 0xff, sizeof(data));
-  ASSERT_TRUE(memory.ReadField(0, &data, &data.two, sizeof(data.two)));
-  ASSERT_FALSE(data.two);
-
-  memset(&data, 0xff, sizeof(data));
-  ASSERT_TRUE(memory.ReadField(0, &data, &data.three, sizeof(data.three)));
-  ASSERT_EQ(0U, data.three);
-
-  memset(&data, 0xff, sizeof(data));
-  ASSERT_TRUE(memory.ReadField(0, &data, &data.four, sizeof(data.four)));
-  ASSERT_EQ(0U, data.four);
-}
-
-TEST(MemoryTest, read_field_fails) {
-  MemoryFakeAlwaysReadZero memory;
-
-  FakeStruct data;
-  memset(&data, 0xff, sizeof(data));
-
-  ASSERT_FALSE(memory.ReadField(UINT64_MAX, &data, &data.three, sizeof(data.three)));
-
-  // Field and start reversed, should fail.
-  ASSERT_FALSE(memory.ReadField(100, &data.two, &data, sizeof(data.two)));
-  ASSERT_FALSE(memory.ReadField(0, &data.two, &data, sizeof(data.two)));
-}
-
 TEST(MemoryTest, read_string) {
   std::string name("string_in_memory");