Clean up OatFile.

In Setup(), avoid reading beyond the end and use the %zu
format specifier instead of %zd for size_t output.

Make the .bss section pointers non-const.

Change-Id: Ic8f066effe8037b552d8e911c6a5d17370d79ff4
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index a82d09e..d6cb65b 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -281,7 +281,7 @@
 
   // Offsets of the dex cache arrays for each app dex file. For the
   // boot image, this information is provided by the ImageWriter.
-  SafeMap<const DexFile*, size_t> dex_cache_arrays_offsets_;
+  SafeMap<const DexFile*, size_t> dex_cache_arrays_offsets_;  // DexFiles not owned.
 
   // Offset of the oat data from the start of the mmapped region of the elf file.
   size_t oat_data_offset_;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 395649e..73fd091 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1208,7 +1208,7 @@
   uint8_t* raw_arrays = nullptr;
   if (dex_file.GetOatDexFile() != nullptr &&
       dex_file.GetOatDexFile()->GetDexCacheArrays() != nullptr) {
-    raw_arrays = const_cast<uint8_t*>(dex_file.GetOatDexFile()->GetDexCacheArrays());
+    raw_arrays = dex_file.GetOatDexFile()->GetDexCacheArrays();
   } else if (dex_file.NumStringIds() != 0u || dex_file.NumTypeIds() != 0u ||
       dex_file.NumMethodIds() != 0u || dex_file.NumFieldIds() != 0u) {
     // NOTE: We "leak" the raw_arrays because we never destroy the dex cache.
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index e861921..80c103e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -18,6 +18,7 @@
 
 #include <dlfcn.h>
 #include <string.h>
+#include <type_traits>
 #include <unistd.h>
 
 #include <cstdlib>
@@ -388,13 +389,13 @@
   // Readjust to be non-inclusive upper bound.
   end_ += sizeof(uint32_t);
 
-  bss_begin_ = elf_file_->FindDynamicSymbolAddress("oatbss");
+  bss_begin_ = const_cast<uint8_t*>(elf_file_->FindDynamicSymbolAddress("oatbss"));
   if (bss_begin_ == nullptr) {
     // No .bss section. Clear dlerror().
     bss_end_ = nullptr;
     dlerror();
   } else {
-    bss_end_ = elf_file_->FindDynamicSymbolAddress("oatbsslastword");
+    bss_end_ = const_cast<uint8_t*>(elf_file_->FindDynamicSymbolAddress("oatbsslastword"));
     if (bss_end_ == nullptr) {
       *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'",
                                 file->GetPath().c_str());
@@ -407,10 +408,31 @@
   return Setup(abs_dex_location, error_msg);
 }
 
+// Read an unaligned entry from the OatDexFile data in OatFile and advance the read
+// position by the number of bytes read, i.e. sizeof(T).
+// Return true on success, false if the read would go beyond the end of the OatFile.
+template <typename T>
+ALWAYS_INLINE static bool ReadOatDexFileData(const OatFile& oat_file,
+                                             /*inout*/const uint8_t** oat,
+                                             /*out*/T* value) {
+  DCHECK(oat != nullptr);
+  DCHECK(value != nullptr);
+  DCHECK_LE(*oat, oat_file.End());
+  if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
+    return false;
+  }
+  static_assert(std::is_trivial<T>::value, "T must be a trivial type");
+  typedef __attribute__((__aligned__(1))) T unaligned_type;
+  *value = *reinterpret_cast<const unaligned_type*>(*oat);
+  *oat += sizeof(T);
+  return true;
+}
+
 bool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) {
   if (!GetOatHeader().IsValid()) {
     std::string cause = GetOatHeader().GetValidationErrorMessage();
-    *error_msg = StringPrintf("Invalid oat header for '%s': %s", GetLocation().c_str(),
+    *error_msg = StringPrintf("Invalid oat header for '%s': %s",
+                              GetLocation().c_str(),
                               cause.c_str());
     return false;
   }
@@ -424,35 +446,42 @@
   oat += GetOatHeader().GetKeyValueStoreSize();
   if (oat > End()) {
     *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: "
-                              "%p + %zd + %ud <= %p", GetLocation().c_str(),
-                              Begin(), sizeof(OatHeader), GetOatHeader().GetKeyValueStoreSize(),
+                                  "%p + %zu + %u <= %p",
+                              GetLocation().c_str(),
+                              Begin(),
+                              sizeof(OatHeader),
+                              GetOatHeader().GetKeyValueStoreSize(),
                               End());
     return false;
   }
 
   size_t pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
-  const uint8_t* dex_cache_arrays = bss_begin_;
+  uint8_t* dex_cache_arrays = bss_begin_;
   uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
   oat_dex_files_storage_.reserve(dex_file_count);
   for (size_t i = 0; i < dex_file_count; i++) {
-    uint32_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
-    if (UNLIKELY(dex_file_location_size == 0U)) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name",
-                                GetLocation().c_str(), i);
+    uint32_t dex_file_location_size;
+    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
+                                    "location size",
+                                GetLocation().c_str(),
+                                i);
       return false;
     }
-    oat += sizeof(dex_file_location_size);
-    if (UNLIKELY(oat > End())) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd truncated after dex file "
-                                "location size", GetLocation().c_str(), i);
+    if (UNLIKELY(dex_file_location_size == 0U)) {
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
+                                GetLocation().c_str(),
+                                i);
       return false;
     }
 
     const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
     oat += dex_file_location_size;
     if (UNLIKELY(oat > End())) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with truncated dex file "
-                                "location", GetLocation().c_str(), i);
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
+                                    "location",
+                                GetLocation().c_str(),
+                                i);
       return false;
     }
 
@@ -460,46 +489,61 @@
         abs_dex_location,
         std::string(dex_file_location_data, dex_file_location_size));
 
-    uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat);
-    oat += sizeof(dex_file_checksum);
-    if (UNLIKELY(oat > End())) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated after "
-                                "dex file checksum", GetLocation().c_str(), i,
+    uint32_t dex_file_checksum;
+    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
+                                    "dex file checksum",
+                                GetLocation().c_str(),
+                                i,
                                 dex_file_location.c_str());
       return false;
     }
 
-    uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat);
+    uint32_t dex_file_offset;
+    if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
+                                    "after dex file offsets",
+                                GetLocation().c_str(),
+                                i,
+                                dex_file_location.c_str());
+      return false;
+    }
     if (UNLIKELY(dex_file_offset == 0U)) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with zero dex "
-                                "file offset", GetLocation().c_str(), i, dex_file_location.c_str());
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
+                                    "file offset",
+                                GetLocation().c_str(),
+                                i,
+                                dex_file_location.c_str());
       return false;
     }
     if (UNLIKELY(dex_file_offset > Size())) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with dex file "
-                                "offset %ud > %zd", GetLocation().c_str(), i,
-                                dex_file_location.c_str(), dex_file_offset, Size());
-      return false;
-    }
-    oat += sizeof(dex_file_offset);
-    if (UNLIKELY(oat > End())) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
-                                "after dex file offsets", GetLocation().c_str(), i,
-                                dex_file_location.c_str());
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
+                                    "offset %u > %zu",
+                                GetLocation().c_str(),
+                                i,
+                                dex_file_location.c_str(),
+                                dex_file_offset,
+                                Size());
       return false;
     }
 
     const uint8_t* dex_file_pointer = Begin() + dex_file_offset;
     if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
-                                "dex file magic '%s'", GetLocation().c_str(), i,
-                                dex_file_location.c_str(), dex_file_pointer);
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
+                                    "dex file magic '%s'",
+                                GetLocation().c_str(),
+                                i,
+                                dex_file_location.c_str(),
+                                dex_file_pointer);
       return false;
     }
     if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid "
-                                "dex file version '%s'", GetLocation().c_str(), i,
-                                dex_file_location.c_str(), dex_file_pointer);
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
+                                    "dex file version '%s'",
+                                GetLocation().c_str(),
+                                i,
+                                dex_file_location.c_str(),
+                                dex_file_pointer);
       return false;
     }
     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
@@ -507,21 +551,26 @@
 
     oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
     if (UNLIKELY(oat > End())) {
-      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated "
-                                "method offsets", GetLocation().c_str(), i,
+      *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
+                                    "method offsets",
+                                GetLocation().c_str(),
+                                i,
                                 dex_file_location.c_str());
       return false;
     }
 
-    const uint8_t* current_dex_cache_arrays = nullptr;
+    uint8_t* current_dex_cache_arrays = nullptr;
     if (dex_cache_arrays != nullptr) {
       DexCacheArraysLayout layout(pointer_size, *header);
       if (layout.Size() != 0u) {
         if (static_cast<size_t>(bss_end_ - dex_cache_arrays) < layout.Size()) {
-          *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with "
-                                    "truncated dex cache arrays, %zd < %zd.",
-                                    GetLocation().c_str(), i, dex_file_location.c_str(),
-                                    static_cast<size_t>(bss_end_ - dex_cache_arrays), layout.Size());
+          *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with "
+                                        "truncated dex cache arrays, %zu < %zu.",
+                                    GetLocation().c_str(),
+                                    i,
+                                    dex_file_location.c_str(),
+                                    static_cast<size_t>(bss_end_ - dex_cache_arrays),
+                                    layout.Size());
           return false;
         }
         current_dex_cache_arrays = dex_cache_arrays;
@@ -553,7 +602,7 @@
   if (dex_cache_arrays != bss_end_) {
     // We expect the bss section to be either empty (dex_cache_arrays and bss_end_
     // both null) or contain just the dex cache arrays and nothing else.
-    *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zd bytes.",
+    *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.",
                               GetLocation().c_str(),
                               static_cast<size_t>(bss_end_ - dex_cache_arrays));
     return false;
@@ -661,7 +710,7 @@
                                 uint32_t dex_file_location_checksum,
                                 const uint8_t* dex_file_pointer,
                                 const uint32_t* oat_class_offsets_pointer,
-                                const uint8_t* dex_cache_arrays)
+                                uint8_t* dex_cache_arrays)
     : oat_file_(oat_file),
       dex_file_location_(dex_file_location),
       canonical_dex_file_location_(canonical_dex_file_location),
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 34f0141..6acdf86 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -301,10 +301,10 @@
   const uint8_t* end_;
 
   // Pointer to the .bss section, if present, otherwise null.
-  const uint8_t* bss_begin_;
+  uint8_t* bss_begin_;
 
   // Pointer to the end of the .bss section, if present, otherwise null.
-  const uint8_t* bss_end_;
+  uint8_t* bss_end_;
 
   // Was this oat_file loaded executable?
   const bool is_executable_;
@@ -396,7 +396,7 @@
   // Returns the offset to the OatClass information. Most callers should use GetOatClass.
   uint32_t GetOatClassOffset(uint16_t class_def_index) const;
 
-  const uint8_t* GetDexCacheArrays() const {
+  uint8_t* GetDexCacheArrays() const {
     return dex_cache_arrays_;
   }
 
@@ -409,7 +409,7 @@
              uint32_t dex_file_checksum,
              const uint8_t* dex_file_pointer,
              const uint32_t* oat_class_offsets_pointer,
-             const uint8_t* dex_cache_arrays);
+             uint8_t* dex_cache_arrays);
 
   const OatFile* const oat_file_;
   const std::string dex_file_location_;
@@ -417,7 +417,7 @@
   const uint32_t dex_file_location_checksum_;
   const uint8_t* const dex_file_pointer_;
   const uint32_t* const oat_class_offsets_pointer_;
-  const uint8_t* const dex_cache_arrays_;
+  uint8_t* const dex_cache_arrays_;
 
   friend class OatFile;
   DISALLOW_COPY_AND_ASSIGN(OatDexFile);