dex2oat.cc revision 65c23bbb25f069b3b49761468b848c4e5d1aa879
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/stat.h>
20#include <valgrind.h>
21
22#include <fstream>
23#include <iostream>
24#include <sstream>
25#include <string>
26#include <vector>
27
28#include "base/stl_util.h"
29#include "base/stringpiece.h"
30#include "base/timing_logger.h"
31#include "base/unix_file/fd_file.h"
32#include "class_linker.h"
33#include "compiler_callbacks.h"
34#include "dex_file-inl.h"
35#include "dex/verification_results.h"
36#include "driver/compiler_driver.h"
37#include "elf_fixup.h"
38#include "elf_stripper.h"
39#include "gc/space/image_space.h"
40#include "gc/space/space-inl.h"
41#include "image_writer.h"
42#include "leb128.h"
43#include "mirror/art_method-inl.h"
44#include "mirror/class-inl.h"
45#include "mirror/class_loader.h"
46#include "mirror/object-inl.h"
47#include "mirror/object_array-inl.h"
48#include "oat_writer.h"
49#include "object_utils.h"
50#include "os.h"
51#include "runtime.h"
52#include "ScopedLocalRef.h"
53#include "scoped_thread_state_change.h"
54#include "sirt_ref.h"
55#include "vector_output_stream.h"
56#include "verifier/method_verifier.h"
57#include "verifier/method_verifier-inl.h"
58#include "well_known_classes.h"
59#include "zip_archive.h"
60
61#include "dex/quick/dex_file_to_method_inliner_map.h"
62
63namespace art {
64
65static void UsageErrorV(const char* fmt, va_list ap) {
66  std::string error;
67  StringAppendV(&error, fmt, ap);
68  LOG(ERROR) << error;
69}
70
71static void UsageError(const char* fmt, ...) {
72  va_list ap;
73  va_start(ap, fmt);
74  UsageErrorV(fmt, ap);
75  va_end(ap);
76}
77
78static void Usage(const char* fmt, ...) {
79  va_list ap;
80  va_start(ap, fmt);
81  UsageErrorV(fmt, ap);
82  va_end(ap);
83
84  UsageError("Usage: dex2oat [options]...");
85  UsageError("");
86  UsageError("  --dex-file=<dex-file>: specifies a .dex file to compile.");
87  UsageError("      Example: --dex-file=/system/framework/core.jar");
88  UsageError("");
89  UsageError("  --zip-fd=<file-descriptor>: specifies a file descriptor of a zip file");
90  UsageError("      containing a classes.dex file to compile.");
91  UsageError("      Example: --zip-fd=5");
92  UsageError("");
93  UsageError("  --zip-location=<zip-location>: specifies a symbolic name for the file");
94  UsageError("      corresponding to the file descriptor specified by --zip-fd.");
95  UsageError("      Example: --zip-location=/system/app/Calculator.apk");
96  UsageError("");
97  UsageError("  --oat-file=<file.oat>: specifies the oat output destination via a filename.");
98  UsageError("      Example: --oat-file=/system/framework/boot.oat");
99  UsageError("");
100  UsageError("  --oat-fd=<number>: specifies the oat output destination via a file descriptor.");
101  UsageError("      Example: --oat-file=/system/framework/boot.oat");
102  UsageError("");
103  UsageError("  --oat-location=<oat-name>: specifies a symbolic name for the file corresponding");
104  UsageError("      to the file descriptor specified by --oat-fd.");
105  UsageError("      Example: --oat-location=/data/dalvik-cache/system@app@Calculator.apk.oat");
106  UsageError("");
107  UsageError("  --oat-symbols=<file.oat>: specifies the oat output destination with full symbols.");
108  UsageError("      Example: --oat-symbols=/symbols/system/framework/boot.oat");
109  UsageError("");
110  UsageError("  --bitcode=<file.bc>: specifies the optional bitcode filename.");
111  UsageError("      Example: --bitcode=/system/framework/boot.bc");
112  UsageError("");
113  UsageError("  --image=<file.art>: specifies the output image filename.");
114  UsageError("      Example: --image=/system/framework/boot.art");
115  UsageError("");
116  UsageError("  --image-classes=<classname-file>: specifies classes to include in an image.");
117  UsageError("      Example: --image=frameworks/base/preloaded-classes");
118  UsageError("");
119  UsageError("  --base=<hex-address>: specifies the base address when creating a boot image.");
120  UsageError("      Example: --base=0x50000000");
121  UsageError("");
122  UsageError("  --boot-image=<file.art>: provide the image file for the boot class path.");
123  UsageError("      Example: --boot-image=/system/framework/boot.art");
124  UsageError("      Default: <host-prefix>/system/framework/boot.art");
125  UsageError("");
126  UsageError("  --host-prefix=<path>: used to translate host paths to target paths during");
127  UsageError("      cross compilation.");
128  UsageError("      Example: --host-prefix=out/target/product/crespo");
129  UsageError("      Default: $ANDROID_PRODUCT_OUT");
130  UsageError("");
131  UsageError("  --android-root=<path>: used to locate libraries for portable linking.");
132  UsageError("      Example: --android-root=out/host/linux-x86");
133  UsageError("      Default: $ANDROID_ROOT");
134  UsageError("");
135  UsageError("  --instruction-set=(arm|mips|x86): compile for a particular instruction");
136  UsageError("      set.");
137  UsageError("      Example: --instruction-set=x86");
138  UsageError("      Default: arm");
139  UsageError("");
140  UsageError("  --instruction-set-features=...,: Specify instruction set features");
141  UsageError("      Example: --instruction-set-features=div");
142  UsageError("      Default: default");
143  UsageError("");
144  UsageError("  --compiler-backend=(Quick|QuickGBC|Portable): select compiler backend");
145  UsageError("      set.");
146  UsageError("      Example: --compiler-backend=Portable");
147  UsageError("      Default: Quick");
148  UsageError("");
149  UsageError("  --host: used with Portable backend to link against host runtime libraries");
150  UsageError("");
151  UsageError("  --dump-timing: display a breakdown of where time was spent");
152  UsageError("");
153  UsageError("  --runtime-arg <argument>: used to specify various arguments for the runtime,");
154  UsageError("      such as initial heap size, maximum heap size, and verbose output.");
155  UsageError("      Use a separate --runtime-arg switch for each argument.");
156  UsageError("      Example: --runtime-arg -Xms256m");
157  UsageError("");
158  std::cerr << "See log for usage error information\n";
159  exit(EXIT_FAILURE);
160}
161
162class Dex2Oat {
163 public:
164  static bool Create(Dex2Oat** p_dex2oat,
165                     Runtime::Options& options,
166                     CompilerBackend compiler_backend,
167                     InstructionSet instruction_set,
168                     InstructionSetFeatures instruction_set_features,
169                     size_t thread_count)
170      SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
171    UniquePtr<Dex2Oat> dex2oat(new Dex2Oat(compiler_backend, instruction_set,
172                                           instruction_set_features, thread_count));
173    if (!dex2oat->CreateRuntime(options, instruction_set)) {
174      *p_dex2oat = NULL;
175      return false;
176    }
177    *p_dex2oat = dex2oat.release();
178    return true;
179  }
180
181  ~Dex2Oat() {
182    delete runtime_;
183    LogCompletionTime();
184  }
185
186  void LogCompletionTime() {
187    LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_)
188              << " (threads: " << thread_count_ << ")";
189  }
190
191
192  // Reads the class names (java.lang.Object) and returns a set of descriptors (Ljava/lang/Object;)
193  CompilerDriver::DescriptorSet* ReadImageClassesFromFile(const char* image_classes_filename) {
194    UniquePtr<std::ifstream> image_classes_file(new std::ifstream(image_classes_filename,
195                                                                  std::ifstream::in));
196    if (image_classes_file.get() == NULL) {
197      LOG(ERROR) << "Failed to open image classes file " << image_classes_filename;
198      return NULL;
199    }
200    UniquePtr<CompilerDriver::DescriptorSet> result(ReadImageClasses(*image_classes_file.get()));
201    image_classes_file->close();
202    return result.release();
203  }
204
205  CompilerDriver::DescriptorSet* ReadImageClasses(std::istream& image_classes_stream) {
206    UniquePtr<CompilerDriver::DescriptorSet> image_classes(new CompilerDriver::DescriptorSet);
207    while (image_classes_stream.good()) {
208      std::string dot;
209      std::getline(image_classes_stream, dot);
210      if (StartsWith(dot, "#") || dot.empty()) {
211        continue;
212      }
213      std::string descriptor(DotToDescriptor(dot.c_str()));
214      image_classes->insert(descriptor);
215    }
216    return image_classes.release();
217  }
218
219  // Reads the class names (java.lang.Object) and returns a set of descriptors (Ljava/lang/Object;)
220  CompilerDriver::DescriptorSet* ReadImageClassesFromZip(const char* zip_filename,
221                                                         const char* image_classes_filename,
222                                                         std::string* error_msg) {
223    UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(zip_filename, error_msg));
224    if (zip_archive.get() == NULL) {
225      return NULL;
226    }
227    UniquePtr<ZipEntry> zip_entry(zip_archive->Find(image_classes_filename, error_msg));
228    if (zip_entry.get() == NULL) {
229      *error_msg = StringPrintf("Failed to find '%s' within '%s': %s", image_classes_filename,
230                                zip_filename, error_msg->c_str());
231      return NULL;
232    }
233    UniquePtr<MemMap> image_classes_file(zip_entry->ExtractToMemMap(image_classes_filename,
234                                                                    error_msg));
235    if (image_classes_file.get() == NULL) {
236      *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", image_classes_filename,
237                                zip_filename, error_msg->c_str());
238      return NULL;
239    }
240    const std::string image_classes_string(reinterpret_cast<char*>(image_classes_file->Begin()),
241                                           image_classes_file->Size());
242    std::istringstream image_classes_stream(image_classes_string);
243    return ReadImageClasses(image_classes_stream);
244  }
245
246  const CompilerDriver* CreateOatFile(const std::string& boot_image_option,
247                                      const std::string* host_prefix,
248                                      const std::string& android_root,
249                                      bool is_host,
250                                      const std::vector<const DexFile*>& dex_files,
251                                      File* oat_file,
252                                      const std::string& bitcode_filename,
253                                      bool image,
254                                      UniquePtr<CompilerDriver::DescriptorSet>& image_classes,
255                                      bool dump_stats,
256                                      TimingLogger& timings) {
257    // SirtRef and ClassLoader creation needs to come after Runtime::Create
258    jobject class_loader = NULL;
259    Thread* self = Thread::Current();
260    if (!boot_image_option.empty()) {
261      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
262      std::vector<const DexFile*> class_path_files(dex_files);
263      OpenClassPathFiles(runtime_->GetClassPathString(), class_path_files);
264      ScopedObjectAccess soa(self);
265      for (size_t i = 0; i < class_path_files.size(); i++) {
266        class_linker->RegisterDexFile(*class_path_files[i]);
267      }
268      soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader);
269      ScopedLocalRef<jobject> class_loader_local(soa.Env(),
270          soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
271      class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
272      Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path_files);
273    }
274
275    UniquePtr<CompilerDriver> driver(new CompilerDriver(verification_results_.get(),
276                                                        method_inliner_map_.get(),
277                                                        compiler_backend_,
278                                                        instruction_set_,
279                                                        instruction_set_features_,
280                                                        image,
281                                                        image_classes.release(),
282                                                        thread_count_,
283                                                        dump_stats));
284
285    if (compiler_backend_ == kPortable) {
286      driver->SetBitcodeFileName(bitcode_filename);
287    }
288
289    driver->CompileAll(class_loader, dex_files, timings);
290
291    timings.NewSplit("dex2oat OatWriter");
292    std::string image_file_location;
293    uint32_t image_file_location_oat_checksum = 0;
294    uint32_t image_file_location_oat_data_begin = 0;
295    if (!driver->IsImage()) {
296      TimingLogger::ScopedSplit split("Loading image checksum", &timings);
297      gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace();
298      image_file_location_oat_checksum = image_space->GetImageHeader().GetOatChecksum();
299      image_file_location_oat_data_begin =
300          reinterpret_cast<uint32_t>(image_space->GetImageHeader().GetOatDataBegin());
301      image_file_location = image_space->GetImageFilename();
302      if (host_prefix != NULL && StartsWith(image_file_location, host_prefix->c_str())) {
303        image_file_location = image_file_location.substr(host_prefix->size());
304      }
305    }
306
307    OatWriter oat_writer(dex_files,
308                         image_file_location_oat_checksum,
309                         image_file_location_oat_data_begin,
310                         image_file_location,
311                         driver.get(),
312                         &timings);
313
314    TimingLogger::ScopedSplit split("Writing ELF", &timings);
315    if (!driver->WriteElf(android_root, is_host, dex_files, oat_writer, oat_file)) {
316      LOG(ERROR) << "Failed to write ELF file " << oat_file->GetPath();
317      return NULL;
318    }
319
320    return driver.release();
321  }
322
323  bool CreateImageFile(const std::string& image_filename,
324                       uintptr_t image_base,
325                       const std::string& oat_filename,
326                       const std::string& oat_location,
327                       const CompilerDriver& compiler)
328      LOCKS_EXCLUDED(Locks::mutator_lock_) {
329    uintptr_t oat_data_begin;
330    {
331      // ImageWriter is scoped so it can free memory before doing FixupElf
332      ImageWriter image_writer(compiler);
333      if (!image_writer.Write(image_filename, image_base, oat_filename, oat_location)) {
334        LOG(ERROR) << "Failed to create image file " << image_filename;
335        return false;
336      }
337      oat_data_begin = image_writer.GetOatDataBegin();
338    }
339
340    UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str()));
341    if (oat_file.get() == NULL) {
342      PLOG(ERROR) << "Failed to open ELF file: " << oat_filename;
343      return false;
344    }
345    if (!ElfFixup::Fixup(oat_file.get(), oat_data_begin)) {
346      LOG(ERROR) << "Failed to fixup ELF file " << oat_file->GetPath();
347      return false;
348    }
349    return true;
350  }
351
352 private:
353  class Dex2OatCompilerCallbacks : public CompilerCallbacks {
354    public:
355      Dex2OatCompilerCallbacks(VerificationResults* verification_results,
356                               DexFileToMethodInlinerMap* method_inliner_map)
357          : verification_results_(verification_results),
358            method_inliner_map_(method_inliner_map) { }
359      virtual ~Dex2OatCompilerCallbacks() { }
360
361      virtual bool MethodVerified(verifier::MethodVerifier* verifier)
362          SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
363        bool result = verification_results_->ProcessVerifiedMethod(verifier);
364        if (result && method_inliner_map_ != nullptr) {
365          MethodReference ref = verifier->GetMethodReference();
366          method_inliner_map_->GetMethodInliner(ref.dex_file)
367              ->AnalyseMethodCode(ref.dex_method_index, verifier->CodeItem());
368        }
369        return result;
370      }
371      virtual void ClassRejected(ClassReference ref) {
372        verification_results_->AddRejectedClass(ref);
373      }
374
375    private:
376      VerificationResults* verification_results_;
377      DexFileToMethodInlinerMap* method_inliner_map_;
378  };
379
380  explicit Dex2Oat(CompilerBackend compiler_backend,
381                   InstructionSet instruction_set,
382                   InstructionSetFeatures instruction_set_features,
383                   size_t thread_count)
384      : compiler_backend_(compiler_backend),
385        instruction_set_(instruction_set),
386        instruction_set_features_(instruction_set_features),
387        verification_results_(new VerificationResults),
388        method_inliner_map_(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr),
389        callbacks_(verification_results_.get(), method_inliner_map_.get()),
390        runtime_(nullptr),
391        thread_count_(thread_count),
392        start_ns_(NanoTime()) {
393  }
394
395  bool CreateRuntime(Runtime::Options& options, InstructionSet instruction_set)
396      SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
397    options.push_back(
398        std::make_pair("compilercallbacks", static_cast<CompilerCallbacks*>(&callbacks_)));
399    if (!Runtime::Create(options, false)) {
400      LOG(ERROR) << "Failed to create runtime";
401      return false;
402    }
403    Runtime* runtime = Runtime::Current();
404    for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
405      Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
406      if (!runtime->HasCalleeSaveMethod(type)) {
407        runtime->SetCalleeSaveMethod(runtime->CreateCalleeSaveMethod(instruction_set, type), type);
408      }
409    }
410    runtime->GetClassLinker()->FixupDexCaches(runtime->GetResolutionMethod());
411    runtime_ = runtime;
412    return true;
413  }
414
415  // Appends to dex_files any elements of class_path that it doesn't already
416  // contain. This will open those dex files as necessary.
417  static void OpenClassPathFiles(const std::string& class_path,
418                                 std::vector<const DexFile*>& dex_files) {
419    std::vector<std::string> parsed;
420    Split(class_path, ':', parsed);
421    // Take Locks::mutator_lock_ so that lock ordering on the ClassLinker::dex_lock_ is maintained.
422    ScopedObjectAccess soa(Thread::Current());
423    for (size_t i = 0; i < parsed.size(); ++i) {
424      if (DexFilesContains(dex_files, parsed[i])) {
425        continue;
426      }
427      std::string error_msg;
428      const DexFile* dex_file = DexFile::Open(parsed[i].c_str(), parsed[i].c_str(), &error_msg);
429      if (dex_file == NULL) {
430        LOG(WARNING) << "Failed to open dex file '" << parsed[i] << "': " << error_msg;
431      } else {
432        dex_files.push_back(dex_file);
433      }
434    }
435  }
436
437  // Returns true if dex_files has a dex with the named location.
438  static bool DexFilesContains(const std::vector<const DexFile*>& dex_files,
439                               const std::string& location) {
440    for (size_t i = 0; i < dex_files.size(); ++i) {
441      if (dex_files[i]->GetLocation() == location) {
442        return true;
443      }
444    }
445    return false;
446  }
447
448  const CompilerBackend compiler_backend_;
449
450  const InstructionSet instruction_set_;
451  const InstructionSetFeatures instruction_set_features_;
452
453  UniquePtr<VerificationResults> verification_results_;
454  UniquePtr<DexFileToMethodInlinerMap> method_inliner_map_;
455  Dex2OatCompilerCallbacks callbacks_;
456  Runtime* runtime_;
457  size_t thread_count_;
458  uint64_t start_ns_;
459
460  DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
461};
462
463static bool ParseInt(const char* in, int* out) {
464  char* end;
465  int result = strtol(in, &end, 10);
466  if (in == end || *end != '\0') {
467    return false;
468  }
469  *out = result;
470  return true;
471}
472
473static size_t OpenDexFiles(const std::vector<const char*>& dex_filenames,
474                           const std::vector<const char*>& dex_locations,
475                           std::vector<const DexFile*>& dex_files) {
476  size_t failure_count = 0;
477  for (size_t i = 0; i < dex_filenames.size(); i++) {
478    const char* dex_filename = dex_filenames[i];
479    const char* dex_location = dex_locations[i];
480    ATRACE_BEGIN(StringPrintf("Opening dex file '%s'", dex_filenames[i]).c_str());
481    std::string error_msg;
482    if (!OS::FileExists(dex_filename)) {
483      LOG(WARNING) << "Skipping non-existent dex file '" << dex_filename << "'";
484      continue;
485    }
486    const DexFile* dex_file = DexFile::Open(dex_filename, dex_location, &error_msg);
487    if (dex_file == NULL) {
488      LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "': " << error_msg;
489      ++failure_count;
490    } else {
491      dex_files.push_back(dex_file);
492    }
493    ATRACE_END();
494  }
495  return failure_count;
496}
497
498// The primary goal of the watchdog is to prevent stuck build servers
499// during development when fatal aborts lead to a cascade of failures
500// that result in a deadlock.
501class WatchDog {
502// WatchDog defines its own CHECK_PTHREAD_CALL to avoid using Log which uses locks
503#undef CHECK_PTHREAD_CALL
504#define CHECK_WATCH_DOG_PTHREAD_CALL(call, args, what) \
505  do { \
506    int rc = call args; \
507    if (rc != 0) { \
508      errno = rc; \
509      std::string message(# call); \
510      message += " failed for "; \
511      message += reason; \
512      Fatal(message); \
513    } \
514  } while (false)
515
516 public:
517  explicit WatchDog(bool is_watch_dog_enabled) {
518    is_watch_dog_enabled_ = is_watch_dog_enabled;
519    if (!is_watch_dog_enabled_) {
520      return;
521    }
522    shutting_down_ = false;
523    const char* reason = "dex2oat watch dog thread startup";
524    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_init, (&mutex_, NULL), reason);
525    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_init, (&cond_, NULL), reason);
526    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_attr_init, (&attr_), reason);
527    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_create, (&pthread_, &attr_, &CallBack, this), reason);
528    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_attr_destroy, (&attr_), reason);
529  }
530  ~WatchDog() {
531    if (!is_watch_dog_enabled_) {
532      return;
533    }
534    const char* reason = "dex2oat watch dog thread shutdown";
535    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&mutex_), reason);
536    shutting_down_ = true;
537    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_signal, (&cond_), reason);
538    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&mutex_), reason);
539
540    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_join, (pthread_, NULL), reason);
541
542    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_cond_destroy, (&cond_), reason);
543    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_destroy, (&mutex_), reason);
544  }
545
546 private:
547  static void* CallBack(void* arg) {
548    WatchDog* self = reinterpret_cast<WatchDog*>(arg);
549    ::art::SetThreadName("dex2oat watch dog");
550    self->Wait();
551    return NULL;
552  }
553
554  static void Message(char severity, const std::string& message) {
555    // TODO: Remove when we switch to LOG when we can guarantee it won't prevent shutdown in error
556    //       cases.
557    fprintf(stderr, "dex2oat%s %c %d %d %s\n",
558            kIsDebugBuild ? "d" : "",
559            severity,
560            getpid(),
561            GetTid(),
562            message.c_str());
563  }
564
565  static void Warn(const std::string& message) {
566    Message('W', message);
567  }
568
569  static void Fatal(const std::string& message) {
570    Message('F', message);
571    exit(1);
572  }
573
574  void Wait() {
575    bool warning = true;
576    CHECK_GT(kWatchDogTimeoutSeconds, kWatchDogWarningSeconds);
577    // TODO: tune the multiplier for GC verification, the following is just to make the timeout
578    //       large.
579    int64_t multiplier = gc::kDesiredHeapVerification > gc::kVerifyAllFast ? 100 : 1;
580    timespec warning_ts;
581    InitTimeSpec(true, CLOCK_REALTIME, multiplier * kWatchDogWarningSeconds * 1000, 0, &warning_ts);
582    timespec timeout_ts;
583    InitTimeSpec(true, CLOCK_REALTIME, multiplier * kWatchDogTimeoutSeconds * 1000, 0, &timeout_ts);
584    const char* reason = "dex2oat watch dog thread waiting";
585    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&mutex_), reason);
586    while (!shutting_down_) {
587      int rc = TEMP_FAILURE_RETRY(pthread_cond_timedwait(&cond_, &mutex_,
588                                                         warning ? &warning_ts
589                                                                 : &timeout_ts));
590      if (rc == ETIMEDOUT) {
591        std::string message(StringPrintf("dex2oat did not finish after %d seconds",
592                                         warning ? kWatchDogWarningSeconds
593                                                 : kWatchDogTimeoutSeconds));
594        if (warning) {
595          Warn(message.c_str());
596          warning = false;
597        } else {
598          Fatal(message.c_str());
599        }
600      } else if (rc != 0) {
601        std::string message(StringPrintf("pthread_cond_timedwait failed: %s",
602                                         strerror(errno)));
603        Fatal(message.c_str());
604      }
605    }
606    CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&mutex_), reason);
607  }
608
609  // When setting timeouts, keep in mind that the build server may not be as fast as your desktop.
610#if ART_USE_PORTABLE_COMPILER
611  static const unsigned int kWatchDogWarningSeconds =  2 * 60;  // 2 minutes.
612  static const unsigned int kWatchDogTimeoutSeconds = 30 * 60;  // 25 minutes + buffer.
613#else
614  static const unsigned int kWatchDogWarningSeconds =  1 * 60;  // 1 minute.
615  static const unsigned int kWatchDogTimeoutSeconds =  6 * 60;  // 5 minutes + buffer.
616#endif
617
618  bool is_watch_dog_enabled_;
619  bool shutting_down_;
620  // TODO: Switch to Mutex when we can guarantee it won't prevent shutdown in error cases.
621  pthread_mutex_t mutex_;
622  pthread_cond_t cond_;
623  pthread_attr_t attr_;
624  pthread_t pthread_;
625};
626const unsigned int WatchDog::kWatchDogWarningSeconds;
627const unsigned int WatchDog::kWatchDogTimeoutSeconds;
628
629// Given a set of instruction features from the build, parse it.  The
630// input 'str' is a comma separated list of feature names.  Parse it and
631// return the InstructionSetFeatures object.
632static InstructionSetFeatures ParseFeatureList(std::string str) {
633  InstructionSetFeatures result;
634  typedef std::vector<std::string> FeatureList;
635  FeatureList features;
636  Split(str, ',', features);
637  for (FeatureList::iterator i = features.begin(); i != features.end(); i++) {
638    std::string feature = Trim(*i);
639    if (feature == "default") {
640      // Nothing to do.
641    } else if (feature == "div") {
642      // Supports divide instruction.
643       result.SetHasDivideInstruction(true);
644    } else if (feature == "nodiv") {
645      // Turn off support for divide instruction.
646      result.SetHasDivideInstruction(false);
647    } else {
648      Usage("Unknown instruction set feature: '%s'", feature.c_str());
649    }
650  }
651  // others...
652  return result;
653}
654
655static int dex2oat(int argc, char** argv) {
656  TimingLogger timings("compiler", false, false);
657
658  InitLogging(argv);
659
660  // Skip over argv[0].
661  argv++;
662  argc--;
663
664  if (argc == 0) {
665    Usage("No arguments specified");
666  }
667
668  std::vector<const char*> dex_filenames;
669  std::vector<const char*> dex_locations;
670  int zip_fd = -1;
671  std::string zip_location;
672  std::string oat_filename;
673  std::string oat_symbols;
674  std::string oat_location;
675  int oat_fd = -1;
676  std::string bitcode_filename;
677  const char* image_classes_zip_filename = NULL;
678  const char* image_classes_filename = NULL;
679  std::string image_filename;
680  std::string boot_image_filename;
681  uintptr_t image_base = 0;
682  UniquePtr<std::string> host_prefix;
683  std::string android_root;
684  std::vector<const char*> runtime_args;
685  int thread_count = sysconf(_SC_NPROCESSORS_CONF);
686#if defined(ART_USE_PORTABLE_COMPILER)
687  CompilerBackend compiler_backend = kPortable;
688#else
689  CompilerBackend compiler_backend = kQuick;
690#endif
691
692  // Take the default set of instruction features from the build.
693  InstructionSetFeatures instruction_set_features =
694      ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES));
695
696#if defined(__arm__)
697  InstructionSet instruction_set = kThumb2;
698#elif defined(__i386__)
699  InstructionSet instruction_set = kX86;
700#elif defined(__mips__)
701  InstructionSet instruction_set = kMips;
702#else
703#error "Unsupported architecture"
704#endif
705
706
707  bool is_host = false;
708  bool dump_stats = false;
709  bool dump_timing = false;
710  bool dump_slow_timing = kIsDebugBuild;
711  bool watch_dog_enabled = !kIsTargetBuild;
712
713
714  for (int i = 0; i < argc; i++) {
715    const StringPiece option(argv[i]);
716    bool log_options = false;
717    if (log_options) {
718      LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
719    }
720    if (option.starts_with("--dex-file=")) {
721      dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
722    } else if (option.starts_with("--dex-location=")) {
723      dex_locations.push_back(option.substr(strlen("--dex-location=")).data());
724    } else if (option.starts_with("--zip-fd=")) {
725      const char* zip_fd_str = option.substr(strlen("--zip-fd=")).data();
726      if (!ParseInt(zip_fd_str, &zip_fd)) {
727        Usage("Failed to parse --zip-fd argument '%s' as an integer", zip_fd_str);
728      }
729    } else if (option.starts_with("--zip-location=")) {
730      zip_location = option.substr(strlen("--zip-location=")).data();
731    } else if (option.starts_with("--oat-file=")) {
732      oat_filename = option.substr(strlen("--oat-file=")).data();
733    } else if (option.starts_with("--oat-symbols=")) {
734      oat_symbols = option.substr(strlen("--oat-symbols=")).data();
735    } else if (option.starts_with("--oat-fd=")) {
736      const char* oat_fd_str = option.substr(strlen("--oat-fd=")).data();
737      if (!ParseInt(oat_fd_str, &oat_fd)) {
738        Usage("Failed to parse --oat-fd argument '%s' as an integer", oat_fd_str);
739      }
740    } else if (option == "--watch-dog") {
741      watch_dog_enabled = true;
742    } else if (option == "--no-watch-dog") {
743      watch_dog_enabled = false;
744    } else if (option.starts_with("-j")) {
745      const char* thread_count_str = option.substr(strlen("-j")).data();
746      if (!ParseInt(thread_count_str, &thread_count)) {
747        Usage("Failed to parse -j argument '%s' as an integer", thread_count_str);
748      }
749    } else if (option.starts_with("--oat-location=")) {
750      oat_location = option.substr(strlen("--oat-location=")).data();
751    } else if (option.starts_with("--bitcode=")) {
752      bitcode_filename = option.substr(strlen("--bitcode=")).data();
753    } else if (option.starts_with("--image=")) {
754      image_filename = option.substr(strlen("--image=")).data();
755    } else if (option.starts_with("--image-classes=")) {
756      image_classes_filename = option.substr(strlen("--image-classes=")).data();
757    } else if (option.starts_with("--image-classes-zip=")) {
758      image_classes_zip_filename = option.substr(strlen("--image-classes-zip=")).data();
759    } else if (option.starts_with("--base=")) {
760      const char* image_base_str = option.substr(strlen("--base=")).data();
761      char* end;
762      image_base = strtoul(image_base_str, &end, 16);
763      if (end == image_base_str || *end != '\0') {
764        Usage("Failed to parse hexadecimal value for option %s", option.data());
765      }
766    } else if (option.starts_with("--boot-image=")) {
767      boot_image_filename = option.substr(strlen("--boot-image=")).data();
768    } else if (option.starts_with("--host-prefix=")) {
769      host_prefix.reset(new std::string(option.substr(strlen("--host-prefix=")).data()));
770    } else if (option.starts_with("--android-root=")) {
771      android_root = option.substr(strlen("--android-root=")).data();
772    } else if (option.starts_with("--instruction-set=")) {
773      StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
774      if (instruction_set_str == "arm") {
775        instruction_set = kThumb2;
776      } else if (instruction_set_str == "mips") {
777        instruction_set = kMips;
778      } else if (instruction_set_str == "x86") {
779        instruction_set = kX86;
780      }
781    } else if (option.starts_with("--instruction-set-features=")) {
782      StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
783      instruction_set_features = ParseFeatureList(str.as_string());
784    } else if (option.starts_with("--compiler-backend=")) {
785      StringPiece backend_str = option.substr(strlen("--compiler-backend=")).data();
786      if (backend_str == "Quick") {
787        compiler_backend = kQuick;
788      } else if (backend_str == "Portable") {
789        compiler_backend = kPortable;
790      }
791    } else if (option == "--host") {
792      is_host = true;
793    } else if (option == "--runtime-arg") {
794      if (++i >= argc) {
795        Usage("Missing required argument for --runtime-arg");
796      }
797      if (log_options) {
798        LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
799      }
800      runtime_args.push_back(argv[i]);
801    } else if (option == "--dump-timing") {
802      dump_timing = true;
803    } else if (option == "--dump-stats") {
804      dump_stats = true;
805    } else {
806      Usage("Unknown argument %s", option.data());
807    }
808  }
809
810  if (oat_filename.empty() && oat_fd == -1) {
811    Usage("Output must be supplied with either --oat-file or --oat-fd");
812  }
813
814  if (!oat_filename.empty() && oat_fd != -1) {
815    Usage("--oat-file should not be used with --oat-fd");
816  }
817
818  if (!oat_symbols.empty() && oat_fd != -1) {
819    Usage("--oat-symbols should not be used with --oat-fd");
820  }
821
822  if (!oat_symbols.empty() && is_host) {
823    Usage("--oat-symbols should not be used with --host");
824  }
825
826  if (oat_fd != -1 && !image_filename.empty()) {
827    Usage("--oat-fd should not be used with --image");
828  }
829
830  if (host_prefix.get() == NULL) {
831    const char* android_product_out = getenv("ANDROID_PRODUCT_OUT");
832    if (android_product_out != NULL) {
833        host_prefix.reset(new std::string(android_product_out));
834    }
835  }
836
837  if (android_root.empty()) {
838    const char* android_root_env_var = getenv("ANDROID_ROOT");
839    if (android_root_env_var == NULL) {
840      Usage("--android-root unspecified and ANDROID_ROOT not set");
841    }
842    android_root += android_root_env_var;
843  }
844
845  bool image = (!image_filename.empty());
846  if (!image && boot_image_filename.empty()) {
847    if (host_prefix.get() == NULL) {
848      boot_image_filename += GetAndroidRoot();
849    } else {
850      boot_image_filename += *host_prefix.get();
851      boot_image_filename += "/system";
852    }
853    boot_image_filename += "/framework/boot.art";
854  }
855  std::string boot_image_option;
856  if (!boot_image_filename.empty()) {
857    boot_image_option += "-Ximage:";
858    boot_image_option += boot_image_filename;
859  }
860
861  if (image_classes_filename != NULL && !image) {
862    Usage("--image-classes should only be used with --image");
863  }
864
865  if (image_classes_filename != NULL && !boot_image_option.empty()) {
866    Usage("--image-classes should not be used with --boot-image");
867  }
868
869  if (image_classes_zip_filename != NULL && image_classes_filename == NULL) {
870    Usage("--image-classes-zip should be used with --image-classes");
871  }
872
873  if (dex_filenames.empty() && zip_fd == -1) {
874    Usage("Input must be supplied with either --dex-file or --zip-fd");
875  }
876
877  if (!dex_filenames.empty() && zip_fd != -1) {
878    Usage("--dex-file should not be used with --zip-fd");
879  }
880
881  if (!dex_filenames.empty() && !zip_location.empty()) {
882    Usage("--dex-file should not be used with --zip-location");
883  }
884
885  if (dex_locations.empty()) {
886    for (size_t i = 0; i < dex_filenames.size(); i++) {
887      dex_locations.push_back(dex_filenames[i]);
888    }
889  } else if (dex_locations.size() != dex_filenames.size()) {
890    Usage("--dex-location arguments do not match --dex-file arguments");
891  }
892
893  if (zip_fd != -1 && zip_location.empty()) {
894    Usage("--zip-location should be supplied with --zip-fd");
895  }
896
897  if (boot_image_option.empty()) {
898    if (image_base == 0) {
899      Usage("Non-zero --base not specified");
900    }
901  }
902
903  std::string oat_stripped(oat_filename);
904  std::string oat_unstripped;
905  if (!oat_symbols.empty()) {
906    oat_unstripped += oat_symbols;
907  } else {
908    oat_unstripped += oat_filename;
909  }
910
911  // Done with usage checks, enable watchdog if requested
912  WatchDog watch_dog(watch_dog_enabled);
913
914  // Check early that the result of compilation can be written
915  UniquePtr<File> oat_file;
916  bool create_file = !oat_unstripped.empty();  // as opposed to using open file descriptor
917  if (create_file) {
918    oat_file.reset(OS::CreateEmptyFile(oat_unstripped.c_str()));
919    if (oat_location.empty()) {
920      oat_location = oat_filename;
921    }
922  } else {
923    oat_file.reset(new File(oat_fd, oat_location));
924    oat_file->DisableAutoClose();
925  }
926  if (oat_file.get() == NULL) {
927    PLOG(ERROR) << "Failed to create oat file: " << oat_location;
928    return EXIT_FAILURE;
929  }
930  if (create_file && fchmod(oat_file->Fd(), 0644) != 0) {
931    PLOG(ERROR) << "Failed to make oat file world readable: " << oat_location;
932    return EXIT_FAILURE;
933  }
934
935  timings.StartSplit("dex2oat Setup");
936  LOG(INFO) << "dex2oat: " << oat_location;
937
938  if (image) {
939    bool has_compiler_filter = false;
940    for (const char* r : runtime_args) {
941      if (strncmp(r, "-compiler-filter:", 17) == 0) {
942        has_compiler_filter = true;
943        break;
944      }
945    }
946    if (!has_compiler_filter) {
947      runtime_args.push_back("-compiler-filter:everything");
948    }
949  }
950
951  Runtime::Options options;
952  std::vector<const DexFile*> boot_class_path;
953  if (boot_image_option.empty()) {
954    size_t failure_count = OpenDexFiles(dex_filenames, dex_locations, boot_class_path);
955    if (failure_count > 0) {
956      LOG(ERROR) << "Failed to open some dex files: " << failure_count;
957      return EXIT_FAILURE;
958    }
959    options.push_back(std::make_pair("bootclasspath", &boot_class_path));
960  } else {
961    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
962  }
963  if (host_prefix.get() != NULL) {
964    options.push_back(std::make_pair("host-prefix", host_prefix->c_str()));
965  }
966  for (size_t i = 0; i < runtime_args.size(); i++) {
967    options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
968  }
969
970#ifdef ART_SEA_IR_MODE
971  options.push_back(std::make_pair("-sea_ir", reinterpret_cast<void*>(NULL)));
972#endif
973
974  Dex2Oat* p_dex2oat;
975  if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set,
976      instruction_set_features, thread_count)) {
977    LOG(ERROR) << "Failed to create dex2oat";
978    return EXIT_FAILURE;
979  }
980  UniquePtr<Dex2Oat> dex2oat(p_dex2oat);
981  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
982  // give it away now so that we don't starve GC.
983  Thread* self = Thread::Current();
984  self->TransitionFromRunnableToSuspended(kNative);
985  // If we're doing the image, override the compiler filter to force full compilation. Must be
986  // done ahead of WellKnownClasses::Init that causes verification.  Note: doesn't force
987  // compilation of class initializers.
988  // Whilst we're in native take the opportunity to initialize well known classes.
989  WellKnownClasses::Init(self->GetJniEnv());
990
991  // If --image-classes was specified, calculate the full list of classes to include in the image
992  UniquePtr<CompilerDriver::DescriptorSet> image_classes(NULL);
993  if (image_classes_filename != NULL) {
994    std::string error_msg;
995    if (image_classes_zip_filename != NULL) {
996      image_classes.reset(dex2oat->ReadImageClassesFromZip(image_classes_zip_filename,
997                                                           image_classes_filename,
998                                                           &error_msg));
999    } else {
1000      image_classes.reset(dex2oat->ReadImageClassesFromFile(image_classes_filename));
1001    }
1002    if (image_classes.get() == NULL) {
1003      LOG(ERROR) << "Failed to create list of image classes from '" << image_classes_filename <<
1004          "': " << error_msg;
1005      return EXIT_FAILURE;
1006    }
1007  }
1008
1009  std::vector<const DexFile*> dex_files;
1010  if (boot_image_option.empty()) {
1011    dex_files = Runtime::Current()->GetClassLinker()->GetBootClassPath();
1012  } else {
1013    if (dex_filenames.empty()) {
1014      ATRACE_BEGIN("Opening zip archive from file descriptor");
1015      std::string error_msg;
1016      UniquePtr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(zip_fd, zip_location.c_str(),
1017                                                               &error_msg));
1018      if (zip_archive.get() == NULL) {
1019        LOG(ERROR) << "Failed to open zip from file descriptor for '" << zip_location << "': "
1020            << error_msg;
1021        return EXIT_FAILURE;
1022      }
1023      const DexFile* dex_file = DexFile::Open(*zip_archive.get(), zip_location, &error_msg);
1024      if (dex_file == NULL) {
1025        LOG(ERROR) << "Failed to open dex from file descriptor for zip file '" << zip_location
1026            << "': " << error_msg;
1027        return EXIT_FAILURE;
1028      }
1029      dex_files.push_back(dex_file);
1030      ATRACE_END();
1031    } else {
1032      size_t failure_count = OpenDexFiles(dex_filenames, dex_locations, dex_files);
1033      if (failure_count > 0) {
1034        LOG(ERROR) << "Failed to open some dex files: " << failure_count;
1035        return EXIT_FAILURE;
1036      }
1037    }
1038
1039    // Ensure opened dex files are writable for dex-to-dex transformations.
1040    for (const auto& dex_file : dex_files) {
1041      if (!dex_file->EnableWrite()) {
1042        PLOG(ERROR) << "Failed to make .dex file writeable '" << dex_file->GetLocation() << "'\n";
1043      }
1044    }
1045  }
1046
1047  /*
1048   * If we're not in interpret-only mode, go ahead and compile small applications. Don't
1049   * bother to check if we're doing the image.
1050   */
1051  if (!image && (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly)) {
1052    size_t num_methods = 0;
1053    for (size_t i = 0; i != dex_files.size(); ++i) {
1054      const DexFile* dex_file = dex_files[i];
1055      CHECK(dex_file != NULL);
1056      num_methods += dex_file->NumMethodIds();
1057    }
1058    if (num_methods <= Runtime::Current()->GetNumDexMethodsThreshold()) {
1059      Runtime::Current()->SetCompilerFilter(Runtime::kSpeed);
1060      VLOG(compiler) << "Below method threshold, compiling anyways";
1061    }
1062  }
1063
1064  UniquePtr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option,
1065                                                                  host_prefix.get(),
1066                                                                  android_root,
1067                                                                  is_host,
1068                                                                  dex_files,
1069                                                                  oat_file.get(),
1070                                                                  bitcode_filename,
1071                                                                  image,
1072                                                                  image_classes,
1073                                                                  dump_stats,
1074                                                                  timings));
1075
1076  if (compiler.get() == NULL) {
1077    LOG(ERROR) << "Failed to create oat file: " << oat_location;
1078    return EXIT_FAILURE;
1079  }
1080
1081  VLOG(compiler) << "Oat file written successfully (unstripped): " << oat_location;
1082
1083  // Notes on the interleaving of creating the image and oat file to
1084  // ensure the references between the two are correct.
1085  //
1086  // Currently we have a memory layout that looks something like this:
1087  //
1088  // +--------------+
1089  // | image        |
1090  // +--------------+
1091  // | boot oat     |
1092  // +--------------+
1093  // | alloc spaces |
1094  // +--------------+
1095  //
1096  // There are several constraints on the loading of the image and boot.oat.
1097  //
1098  // 1. The image is expected to be loaded at an absolute address and
1099  // contains Objects with absolute pointers within the image.
1100  //
1101  // 2. There are absolute pointers from Methods in the image to their
1102  // code in the oat.
1103  //
1104  // 3. There are absolute pointers from the code in the oat to Methods
1105  // in the image.
1106  //
1107  // 4. There are absolute pointers from code in the oat to other code
1108  // in the oat.
1109  //
1110  // To get this all correct, we go through several steps.
1111  //
1112  // 1. We have already created that oat file above with
1113  // CreateOatFile. Originally this was just our own proprietary file
1114  // but now it is contained within an ELF dynamic object (aka an .so
1115  // file). The Compiler returned by CreateOatFile provides
1116  // PatchInformation for references to oat code and Methods that need
1117  // to be update once we know where the oat file will be located
1118  // after the image.
1119  //
1120  // 2. We create the image file. It needs to know where the oat file
1121  // will be loaded after itself. Originally when oat file was simply
1122  // memory mapped so we could predict where its contents were based
1123  // on the file size. Now that it is an ELF file, we need to inspect
1124  // the ELF file to understand the in memory segment layout including
1125  // where the oat header is located within. ImageWriter's
1126  // PatchOatCodeAndMethods uses the PatchInformation from the
1127  // Compiler to touch up absolute references in the oat file.
1128  //
1129  // 3. We fixup the ELF program headers so that dlopen will try to
1130  // load the .so at the desired location at runtime by offsetting the
1131  // Elf32_Phdr.p_vaddr values by the desired base address.
1132  //
1133  if (image) {
1134    timings.NewSplit("dex2oat ImageWriter");
1135    bool image_creation_success = dex2oat->CreateImageFile(image_filename,
1136                                                           image_base,
1137                                                           oat_unstripped,
1138                                                           oat_location,
1139                                                           *compiler.get());
1140    if (!image_creation_success) {
1141      return EXIT_FAILURE;
1142    }
1143    VLOG(compiler) << "Image written successfully: " << image_filename;
1144  }
1145
1146  if (is_host) {
1147    if (dump_timing || (dump_slow_timing && timings.GetTotalNs() > MsToNs(1000))) {
1148      LOG(INFO) << Dumpable<TimingLogger>(timings);
1149    }
1150    return EXIT_SUCCESS;
1151  }
1152
1153  // If we don't want to strip in place, copy from unstripped location to stripped location.
1154  // We need to strip after image creation because FixupElf needs to use .strtab.
1155  if (oat_unstripped != oat_stripped) {
1156    timings.NewSplit("dex2oat OatFile copy");
1157    oat_file.reset();
1158     UniquePtr<File> in(OS::OpenFileForReading(oat_unstripped.c_str()));
1159    UniquePtr<File> out(OS::CreateEmptyFile(oat_stripped.c_str()));
1160    size_t buffer_size = 8192;
1161    UniquePtr<uint8_t> buffer(new uint8_t[buffer_size]);
1162    while (true) {
1163      int bytes_read = TEMP_FAILURE_RETRY(read(in->Fd(), buffer.get(), buffer_size));
1164      if (bytes_read <= 0) {
1165        break;
1166      }
1167      bool write_ok = out->WriteFully(buffer.get(), bytes_read);
1168      CHECK(write_ok);
1169    }
1170    oat_file.reset(out.release());
1171    VLOG(compiler) << "Oat file copied successfully (stripped): " << oat_stripped;
1172  }
1173
1174#if ART_USE_PORTABLE_COMPILER  // We currently only generate symbols on Portable
1175  timings.NewSplit("dex2oat ElfStripper");
1176  // Strip unneeded sections for target
1177  off_t seek_actual = lseek(oat_file->Fd(), 0, SEEK_SET);
1178  CHECK_EQ(0, seek_actual);
1179  std::string error_msg;
1180  CHECK(ElfStripper::Strip(oat_file.get(), &error_msg)) << error_msg;
1181
1182
1183  // We wrote the oat file successfully, and want to keep it.
1184  VLOG(compiler) << "Oat file written successfully (stripped): " << oat_location;
1185#endif  // ART_USE_PORTABLE_COMPILER
1186
1187  timings.EndSplit();
1188
1189  if (dump_timing || (dump_slow_timing && timings.GetTotalNs() > MsToNs(1000))) {
1190    LOG(INFO) << Dumpable<TimingLogger>(timings);
1191  }
1192
1193  // Everything was successfully written, do an explicit exit here to avoid running Runtime
1194  // destructors that take time (bug 10645725) unless we're a debug build or running on valgrind.
1195  if (!kIsDebugBuild || (RUNNING_ON_VALGRIND == 0)) {
1196    dex2oat->LogCompletionTime();
1197    exit(EXIT_SUCCESS);
1198  }
1199
1200  return EXIT_SUCCESS;
1201}
1202}  // namespace art
1203
1204int main(int argc, char** argv) {
1205  return art::dex2oat(argc, argv);
1206}
1207