Try to mmap vdex file within the address range of the ELF file.

Add ELF section for the vdex file and mmap it there at runtime.
This ensures that the data is at predictable location, which
is needed to be able to reference it from native debug-info.

This does not change the amount of memory allocated, or the
location of the data on disk.  However, it does change how
the memory is allocated - it replaces two allocations
(ELF and vdex) by just one (ELF which includes the vdex).

Bug: 71579677
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing

Change-Id: Ie2abd36c8b6617a527368e71f932998bbe5ad38c
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index c20aa11..73820c1 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -194,10 +194,6 @@
 
   ret->PreLoad();
 
-  if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
-    return nullptr;
-  }
-
   if (!ret->Load(elf_filename,
                  oat_file_begin,
                  writable,
@@ -211,6 +207,10 @@
     return nullptr;
   }
 
+  if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
+    return nullptr;
+  }
+
   ret->PreSetup(elf_filename);
 
   if (!ret->Setup(abs_dex_location, error_msg)) {
@@ -234,10 +234,6 @@
                                       std::string* error_msg) {
   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable));
 
-  if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) {
-    return nullptr;
-  }
-
   if (!ret->Load(oat_fd,
                  oat_file_begin,
                  writable,
@@ -251,6 +247,10 @@
     return nullptr;
   }
 
+  if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) {
+    return nullptr;
+  }
+
   ret->PreSetup(oat_location);
 
   if (!ret->Setup(abs_dex_location, error_msg)) {
@@ -264,7 +264,14 @@
                            bool writable,
                            bool low_4gb,
                            std::string* error_msg) {
-  vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, /* unquicken*/ false, error_msg);
+  vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
+                                  vdex_end_ - vdex_begin_,
+                                  true /* mmap_reuse */,
+                                  vdex_filename,
+                                  writable,
+                                  low_4gb,
+                                  /* unquicken*/ false,
+                                  error_msg);
   if (vdex_.get() == nullptr) {
     *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
                               vdex_filename.c_str(),
@@ -285,13 +292,16 @@
     if (rc == -1) {
       PLOG(WARNING) << "Failed getting length of vdex file";
     } else {
-      vdex_ = VdexFile::Open(vdex_fd,
-                             s.st_size,
-                             vdex_filename,
-                             writable,
-                             low_4gb,
-                             false /* unquicken */,
-                             error_msg);
+      vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
+                                      vdex_end_ - vdex_begin_,
+                                      true /* mmap_reuse */,
+                                      vdex_fd,
+                                      s.st_size,
+                                      vdex_filename,
+                                      writable,
+                                      low_4gb,
+                                      false /* unquicken */,
+                                      error_msg);
       if (vdex_.get() == nullptr) {
         *error_msg = "Failed opening vdex file.";
         return false;
@@ -339,7 +349,7 @@
   } else {
     bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
     if (bss_end_ == nullptr) {
-      *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", file_path.c_str());
+      *error_msg = StringPrintf("Failed to find oatbsslastword symbol in '%s'", file_path.c_str());
       return false;
     }
     // Readjust to be non-inclusive upper bound.
@@ -351,6 +361,20 @@
     bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
   }
 
+  vdex_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdex", &symbol_error_msg));
+  if (vdex_begin_ == nullptr) {
+    // No .vdex section.
+    vdex_end_ = nullptr;
+  } else {
+    vdex_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdexlastword", &symbol_error_msg));
+    if (vdex_end_ == nullptr) {
+      *error_msg = StringPrintf("Failed to find oatdexlastword symbol in '%s'", file_path.c_str());
+      return false;
+    }
+    // Readjust to be non-inclusive upper bound.
+    vdex_end_ += sizeof(uint32_t);
+  }
+
   return true;
 }
 
@@ -1449,6 +1473,8 @@
       bss_methods_(nullptr),
       bss_roots_(nullptr),
       is_executable_(is_executable),
+      vdex_begin_(nullptr),
+      vdex_end_(nullptr),
       secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
   CHECK(!location_.empty());
 }
@@ -1479,6 +1505,14 @@
   return bss_end_;
 }
 
+const uint8_t* OatFile::VdexBegin() const {
+  return vdex_begin_;
+}
+
+const uint8_t* OatFile::VdexEnd() const {
+  return vdex_end_;
+}
+
 const uint8_t* OatFile::DexBegin() const {
   return vdex_->Begin();
 }