Generate unstripped .oat files in the symbols directory.

Test: Check the generated files with readelf.
Bug: 70512966
Change-Id: Id31232f8b750281bdc170f356833a8d71e1b5796
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index cbc6424..0b68620 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -253,7 +253,14 @@
   UsageError("      to the file descriptor specified by --oat-fd.");
   UsageError("      Example: --oat-location=/data/dalvik-cache/system@app@Calculator.apk.oat");
   UsageError("");
-  UsageError("  --oat-symbols=<file.oat>: specifies an oat output destination with full symbols.");
+  UsageError("  --oat-symbols=<file.oat>: specifies a destination where the oat file is copied.");
+  UsageError("      This is equivalent to file copy as build post-processing step.");
+  UsageError("      It is intended to be used with --strip and it happens before it.");
+  UsageError("      Example: --oat-symbols=/symbols/system/framework/boot.oat");
+  UsageError("");
+  UsageError("  --strip: remove all debugging sections at the end (but keep mini-debug-info).");
+  UsageError("      This is equivalent to the \"strip\" command as build post-processing step.");
+  UsageError("      It is intended to be used with --oat-symbols and it happens after it.");
   UsageError("      Example: --oat-symbols=/symbols/system/framework/boot.oat");
   UsageError("");
   UsageError("  --image=<file.art>: specifies an output image filename.");
@@ -1180,6 +1187,7 @@
     AssignIfExists(args, M::DexLocations, &dex_locations_);
     AssignIfExists(args, M::OatFiles, &oat_filenames_);
     AssignIfExists(args, M::OatSymbols, &parser_options->oat_symbols);
+    AssignTrueIfExists(args, M::Strip, &strip_);
     AssignIfExists(args, M::ImageFilenames, &image_filenames_);
     AssignIfExists(args, M::ZipFd, &zip_fd_);
     AssignIfExists(args, M::ZipLocation, &zip_location_);
@@ -2175,7 +2183,7 @@
         VLOG(compiler) << "Oat file written successfully: " << oat_filenames_[i];
 
         oat_writer.reset();
-        elf_writer.reset();
+        // We may still need the ELF writer later for stripping.
       }
     }
 
@@ -2194,21 +2202,16 @@
     return true;
   }
 
-  // Create a copy from stripped to unstripped.
-  bool CopyStrippedToUnstripped() {
+  // Copy the full oat files to symbols directory and then strip the originals.
+  bool CopyOatFilesToSymbolsDirectoryAndStrip() {
     for (size_t i = 0; i < oat_unstripped_.size(); ++i) {
       // If we don't want to strip in place, copy from stripped location to unstripped location.
       // We need to strip after image creation because FixupElf needs to use .strtab.
       if (strcmp(oat_unstripped_[i], oat_filenames_[i]) != 0) {
-        // If the oat file is still open, flush it.
-        if (oat_files_[i].get() != nullptr && oat_files_[i]->IsOpened()) {
-          if (!FlushCloseOutputFile(&oat_files_[i])) {
-            return false;
-          }
-        }
+        DCHECK(oat_files_[i].get() != nullptr && oat_files_[i]->IsOpened());
 
         TimingLogger::ScopedTiming t("dex2oat OatFile copy", timings_);
-        std::unique_ptr<File> in(OS::OpenFileForReading(oat_filenames_[i]));
+        std::unique_ptr<File>& in = oat_files_[i];
         std::unique_ptr<File> out(OS::CreateEmptyFile(oat_unstripped_[i]));
         int64_t in_length = in->GetLength();
         if (in_length < 0) {
@@ -2224,6 +2227,14 @@
           return false;
         }
         VLOG(compiler) << "Oat file copied successfully (unstripped): " << oat_unstripped_[i];
+
+        if (strip_) {
+          TimingLogger::ScopedTiming t2("dex2oat OatFile strip", timings_);
+          if (!elf_writers_[i]->StripDebugInfo()) {
+            PLOG(ERROR) << "Failed strip oat file: " << in->GetPath();
+            return false;
+          }
+        }
       }
     }
     return true;
@@ -2239,11 +2250,10 @@
     return true;
   }
 
-  bool FlushCloseOutputFile(std::unique_ptr<File>* file) {
-    if (file->get() != nullptr) {
-      std::unique_ptr<File> tmp(file->release());
-      if (tmp->FlushCloseOrErase() != 0) {
-        PLOG(ERROR) << "Failed to flush and close output file: " << tmp->GetPath();
+  bool FlushCloseOutputFile(File* file) {
+    if (file != nullptr) {
+      if (file->FlushCloseOrErase() != 0) {
+        PLOG(ERROR) << "Failed to flush and close output file: " << file->GetPath();
         return false;
       }
     }
@@ -2266,7 +2276,7 @@
     bool result = true;
     for (auto& files : { &vdex_files_, &oat_files_ }) {
       for (size_t i = 0; i < files->size(); ++i) {
-        result &= FlushCloseOutputFile(&(*files)[i]);
+        result &= FlushCloseOutputFile((*files)[i].get());
       }
     }
     return result;
@@ -2825,6 +2835,7 @@
   std::string oat_location_;
   std::vector<const char*> oat_filenames_;
   std::vector<const char*> oat_unstripped_;
+  bool strip_;
   int oat_fd_;
   int input_vdex_fd_;
   int output_vdex_fd_;
@@ -2947,15 +2958,9 @@
     return dex2oat::ReturnCode::kOther;
   }
 
-  // Flush boot.oat. We always expect the output file by name, and it will be re-opened from the
-  // unstripped name. Do not close the file if we are compiling the image with an oat fd since the
-  // image writer will require this fd to generate the image.
-  if (dex2oat.ShouldKeepOatFileOpen()) {
-    if (!dex2oat.FlushOutputFiles()) {
-      dex2oat.EraseOutputFiles();
-      return dex2oat::ReturnCode::kOther;
-    }
-  } else if (!dex2oat.FlushCloseOutputFiles()) {
+  // Flush boot.oat.  Keep it open as we might still modify it later (strip it).
+  if (!dex2oat.FlushOutputFiles()) {
+    dex2oat.EraseOutputFiles();
     return dex2oat::ReturnCode::kOther;
   }
 
@@ -2974,7 +2979,7 @@
   }
 
   // Copy stripped to unstripped location, if necessary.
-  if (!dex2oat.CopyStrippedToUnstripped()) {
+  if (!dex2oat.CopyOatFilesToSymbolsDirectoryAndStrip()) {
     return dex2oat::ReturnCode::kOther;
   }
 
@@ -3012,7 +3017,7 @@
 
   // Copy stripped to unstripped location, if necessary. This will implicitly flush & close the
   // stripped versions. If this is given, we expect to be able to open writable files by name.
-  if (!dex2oat.CopyStrippedToUnstripped()) {
+  if (!dex2oat.CopyOatFilesToSymbolsDirectoryAndStrip()) {
     return dex2oat::ReturnCode::kOther;
   }