Add support for .bss section in oat files.

Change-Id: I779b80b8139d9afdc28373f8c68edff5df7726ce
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index a22e274..3490bcf 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1370,7 +1370,7 @@
       reservation_name += file_->GetPath();
       std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
                                                            reserve_base_override,
-                                                           GetLoadedSize(), PROT_NONE, false,
+                                                           GetLoadedSize(), PROT_NONE, false, false,
                                                            error_msg));
       if (reserve.get() == nullptr) {
         *error_msg = StringPrintf("Failed to allocate %s: %s",
@@ -1411,32 +1411,72 @@
     } else {
       flags |= MAP_PRIVATE;
     }
-    if (file_length < (program_header->p_offset + program_header->p_memsz)) {
-      *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
-                                "%d of %" PRIu64 " bytes: '%s'", file_length, i,
-                                static_cast<uint64_t>(program_header->p_offset + program_header->p_memsz),
+    if (program_header->p_filesz > program_header->p_memsz) {
+      *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s",
+                                static_cast<uint64_t>(program_header->p_filesz),
+                                static_cast<uint64_t>(program_header->p_memsz),
                                 file_->GetPath().c_str());
       return false;
     }
-    std::unique_ptr<MemMap> segment(MemMap::MapFileAtAddress(p_vaddr,
-                                                       program_header->p_memsz,
-                                                       prot, flags, file_->Fd(),
-                                                       program_header->p_offset,
-                                                       true,  // implies MAP_FIXED
-                                                       file_->GetPath().c_str(),
-                                                       error_msg));
-    if (segment.get() == nullptr) {
-      *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
-                                i, file_->GetPath().c_str(), error_msg->c_str());
+    if (program_header->p_filesz < program_header->p_memsz &&
+        !IsAligned<kPageSize>(program_header->p_filesz)) {
+      *error_msg = StringPrintf("Unsupported unaligned p_filesz < p_memsz (%" PRIu64
+                                " < %" PRIu64 "): %s",
+                                static_cast<uint64_t>(program_header->p_filesz),
+                                static_cast<uint64_t>(program_header->p_memsz),
+                                file_->GetPath().c_str());
       return false;
     }
-    if (segment->Begin() != p_vaddr) {
-      *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
-                                "instead mapped to %p",
-                                i, file_->GetPath().c_str(), p_vaddr, segment->Begin());
+    if (file_length < (program_header->p_offset + program_header->p_filesz)) {
+      *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
+                                "%d of %" PRIu64 " bytes: '%s'", file_length, i,
+                                static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz),
+                                file_->GetPath().c_str());
       return false;
     }
-    segments_.push_back(segment.release());
+    if (program_header->p_filesz != 0u) {
+      std::unique_ptr<MemMap> segment(
+          MemMap::MapFileAtAddress(p_vaddr,
+                                   program_header->p_filesz,
+                                   prot, flags, file_->Fd(),
+                                   program_header->p_offset,
+                                   true,  // implies MAP_FIXED
+                                   file_->GetPath().c_str(),
+                                   error_msg));
+      if (segment.get() == nullptr) {
+        *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
+                                  i, file_->GetPath().c_str(), error_msg->c_str());
+        return false;
+      }
+      if (segment->Begin() != p_vaddr) {
+        *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
+                                  "instead mapped to %p",
+                                  i, file_->GetPath().c_str(), p_vaddr, segment->Begin());
+        return false;
+      }
+      segments_.push_back(segment.release());
+    }
+    if (program_header->p_filesz < program_header->p_memsz) {
+      std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s",
+                                      static_cast<uint64_t>(i), file_->GetPath().c_str());
+      std::unique_ptr<MemMap> segment(
+          MemMap::MapAnonymous(name.c_str(),
+                               p_vaddr + program_header->p_filesz,
+                               program_header->p_memsz - program_header->p_filesz,
+                               prot, false, true /* reuse */, error_msg));
+      if (segment == nullptr) {
+        *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s",
+                                  i, file_->GetPath().c_str(), error_msg->c_str());
+        return false;
+      }
+      if (segment->Begin() != p_vaddr) {
+        *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s "
+                                  "at expected address %p, instead mapped to %p",
+                                  i, file_->GetPath().c_str(), p_vaddr, segment->Begin());
+        return false;
+      }
+      segments_.push_back(segment.release());
+    }
   }
 
   // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash