13774335b08076117d6950cd472cdd59a167470b5Igor Murashkin/*
23774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * Copyright (C) 2014 The Android Open Source Project
33774335b08076117d6950cd472cdd59a167470b5Igor Murashkin *
43774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
53774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * you may not use this file except in compliance with the License.
63774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * You may obtain a copy of the License at
73774335b08076117d6950cd472cdd59a167470b5Igor Murashkin *
83774335b08076117d6950cd472cdd59a167470b5Igor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
93774335b08076117d6950cd472cdd59a167470b5Igor Murashkin *
103774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * Unless required by applicable law or agreed to in writing, software
113774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
123774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * See the License for the specific language governing permissions and
143774335b08076117d6950cd472cdd59a167470b5Igor Murashkin * limitations under the License.
153774335b08076117d6950cd472cdd59a167470b5Igor Murashkin */
163774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
173774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#ifndef ART_CMDLINE_CMDLINE_H_
183774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#define ART_CMDLINE_CMDLINE_H_
193774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
203774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include <stdio.h>
213774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include <stdlib.h>
223774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
233774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include <fstream>
243774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include <iostream>
253774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include <string>
263774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
273774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include "runtime.h"
283774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include "base/stringpiece.h"
293774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include "noop_compiler_callbacks.h"
303774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#include "base/logging.h"
313774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
323774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#if !defined(NDEBUG)
333774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#define DBG_LOG LOG(INFO)
343774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#else
353774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#define DBG_LOG LOG(DEBUG)
363774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#endif
373774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
383774335b08076117d6950cd472cdd59a167470b5Igor Murashkinnamespace art {
393774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
403774335b08076117d6950cd472cdd59a167470b5Igor Murashkin// TODO: Move to <runtime/utils.h> and remove all copies of this function.
413774335b08076117d6950cd472cdd59a167470b5Igor Murashkinstatic bool LocationToFilename(const std::string& location, InstructionSet isa,
423774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                               std::string* filename) {
433774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  bool has_system = false;
443774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  bool has_cache = false;
453774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // image_location = /system/framework/boot.art
463774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // system_image_filename = /system/framework/<image_isa>/boot.art
473774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::string system_filename(GetSystemImageFilename(location.c_str(), isa));
483774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  if (OS::FileExists(system_filename.c_str())) {
493774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    has_system = true;
503774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
513774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
523774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  bool have_android_data = false;
533774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  bool dalvik_cache_exists = false;
543774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  bool is_global_cache = false;
553774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::string dalvik_cache;
563774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  GetDalvikCache(GetInstructionSetString(isa), false, &dalvik_cache,
573774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                 &have_android_data, &dalvik_cache_exists, &is_global_cache);
583774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
593774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::string cache_filename;
603774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  if (have_android_data && dalvik_cache_exists) {
613774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // Always set output location even if it does not exist,
623774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // so that the caller knows where to create the image.
633774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    //
643774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // image_location = /system/framework/boot.art
653774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // *image_filename = /data/dalvik-cache/<image_isa>/boot.art
663774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::string error_msg;
673774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(),
683774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                               &cache_filename, &error_msg)) {
693774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      has_cache = true;
703774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
713774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
723774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  if (has_system) {
733774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    *filename = system_filename;
743774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
753774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  } else if (has_cache) {
763774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    *filename = cache_filename;
773774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
783774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  } else {
793774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return false;
803774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
813774335b08076117d6950cd472cdd59a167470b5Igor Murashkin}
823774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
83dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Haostatic Runtime* StartRuntime(const char* boot_image_location, InstructionSet instruction_set) {
843774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  CHECK(boot_image_location != nullptr);
853774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
863774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  RuntimeOptions options;
873774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
883774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // We are more like a compiler than a run-time. We don't want to execute code.
893774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  {
903774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    static NoopCompilerCallbacks callbacks;
913774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    options.push_back(std::make_pair("compilercallbacks", &callbacks));
923774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
933774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
943774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Boot image location.
953774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  {
963774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::string boot_image_option;
973774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    boot_image_option += "-Ximage:";
983774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    boot_image_option += boot_image_location;
993774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    options.push_back(std::make_pair(boot_image_option.c_str(), nullptr));
1003774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
1013774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1023774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Instruction set.
1033774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  options.push_back(
1043774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      std::make_pair("imageinstructionset",
1053774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                     reinterpret_cast<const void*>(GetInstructionSetString(instruction_set))));
10601aaf6ef3e3e35cc8e41cf3fe899a7bf337042f4Calin Juravle  // None of the command line tools need sig chain. If this changes we'll need
10701aaf6ef3e3e35cc8e41cf3fe899a7bf337042f4Calin Juravle  // to upgrade this option to a proper parameter.
10801aaf6ef3e3e35cc8e41cf3fe899a7bf337042f4Calin Juravle  options.push_back(std::make_pair("-Xno-sig-chain", nullptr));
1093774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  if (!Runtime::Create(options, false)) {
1103774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    fprintf(stderr, "Failed to create runtime\n");
1113774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return nullptr;
1123774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
1133774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1143774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
1153774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // give it away now and then switch to a more manageable ScopedObjectAccess.
1163774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
1173774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1183774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  return Runtime::Current();
1193774335b08076117d6950cd472cdd59a167470b5Igor Murashkin}
1203774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1213774335b08076117d6950cd472cdd59a167470b5Igor Murashkinstruct CmdlineArgs {
1223774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  enum ParseStatus {
1233774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    kParseOk,               // Parse successful. Do not set the error message.
1243774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    kParseUnknownArgument,  // Unknown argument. Do not set the error message.
1253774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    kParseError,            // Parse ok, but failed elsewhere. Print the set error message.
1263774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  };
1273774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1283774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  bool Parse(int argc, char** argv) {
1293774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // Skip over argv[0].
1303774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    argv++;
1313774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    argc--;
1323774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1333774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (argc == 0) {
1343774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      fprintf(stderr, "No arguments specified\n");
1353774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      PrintUsage();
1363774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      return false;
1373774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
1383774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1393774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::string error_msg;
1403774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    for (int i = 0; i < argc; i++) {
1413774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      const StringPiece option(argv[i]);
1423774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (option.starts_with("--boot-image=")) {
1433774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        boot_image_location_ = option.substr(strlen("--boot-image=")).data();
1443774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      } else if (option.starts_with("--instruction-set=")) {
1453774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
1463774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        instruction_set_ = GetInstructionSetFromString(instruction_set_str.data());
1473774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (instruction_set_ == kNone) {
1483774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "Unsupported instruction set %s\n", instruction_set_str.data());
1493774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1503774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1513774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1523774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      } else if (option.starts_with("--output=")) {
1533774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        output_name_ = option.substr(strlen("--output=")).ToString();
1543774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        const char* filename = output_name_.c_str();
1553774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        out_.reset(new std::ofstream(filename));
1563774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (!out_->good()) {
1573774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "Failed to open output filename %s\n", filename);
1583774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1593774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1603774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1613774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        os_ = out_.get();
1623774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      } else {
1633774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        ParseStatus parse_status = ParseCustom(option, &error_msg);
1643774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1653774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (parse_status == kParseUnknownArgument) {
1663774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "Unknown argument %s\n", option.data());
1673774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1683774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1693774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (parse_status != kParseOk) {
1703774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "%s\n", error_msg.c_str());
1713774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1723774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1733774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1743774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
1753774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
1763774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1773774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    DBG_LOG << "will call parse checks";
1783774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1793774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    {
1803774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      ParseStatus checks_status = ParseChecks(&error_msg);
1813774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (checks_status != kParseOk) {
1823774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "%s\n", error_msg.c_str());
1833774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1843774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1853774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
1863774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
1873774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1883774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
1893774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
1903774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1913774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual std::string GetUsage() const {
1923774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::string usage;
1933774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1943774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    usage +=  // Required.
1953774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "  --boot-image=<file.art>: provide the image location for the boot class path.\n"
1963774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Do not include the arch as part of the name, it is added automatically.\n"
1973774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Example: --boot-image=/system/framework/boot.art\n"
19864fff41f639a7b85b2e172977175b3c79151634eKevin Brodsky        "               (specifies /system/framework/<arch>/boot.art as the image file)\n"
1993774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "\n";
2003774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    usage += StringPrintf(  // Optional.
20157b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe        "  --instruction-set=(arm|arm64|mips|mips64|x86|x86_64): for locating the image\n"
2023774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      file based on the image location set.\n"
2033774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Example: --instruction-set=x86\n"
2043774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Default: %s\n"
2053774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "\n",
2063774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        GetInstructionSetString(kRuntimeISA));
2073774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    usage +=  // Optional.
2083774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "  --output=<file> may be used to send the output to a file.\n"
2093774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Example: --output=/tmp/oatdump.txt\n"
2103774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "\n";
2113774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2123774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return usage;
2133774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
2143774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2153774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Specified by --boot-image.
2163774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  const char* boot_image_location_ = nullptr;
2173774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Specified by --instruction-set.
2183774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  InstructionSet instruction_set_ = kRuntimeISA;
2193774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Specified by --output.
2203774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::ostream* os_ = &std::cout;
2213774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::unique_ptr<std::ofstream> out_;  // If something besides cout is used
2223774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::string output_name_;
2233774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2243774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual ~CmdlineArgs() {}
2253774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
226c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  bool ParseCheckBootImage(std::string* error_msg) {
2273774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (boot_image_location_ == nullptr) {
2283774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      *error_msg = "--boot-image must be specified";
229c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      return false;
2303774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
2313774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2323774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    DBG_LOG << "boot image location: " << boot_image_location_;
2333774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2343774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // Checks for --boot-image location.
2353774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    {
2363774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      std::string boot_image_location = boot_image_location_;
2373774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      size_t file_name_idx = boot_image_location.rfind("/");
2383774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (file_name_idx == std::string::npos) {  // Prevent a InsertIsaDirectory check failure.
2393774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        *error_msg = "Boot image location must have a / in it";
240c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return false;
2413774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
2423774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2433774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      // Don't let image locations with the 'arch' in it through, since it's not a location.
2443774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      // This prevents a common error "Could not create an image space..." when initing the Runtime.
2453774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (file_name_idx != std::string::npos) {
2463774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        std::string no_file_name = boot_image_location.substr(0, file_name_idx);
2473774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        size_t ancestor_dirs_idx = no_file_name.rfind("/");
2483774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2493774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        std::string parent_dir_name;
2503774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (ancestor_dirs_idx != std::string::npos) {
2513774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          parent_dir_name = no_file_name.substr(ancestor_dirs_idx + 1);
2523774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        } else {
2533774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          parent_dir_name = no_file_name;
2543774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
2553774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2563774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        DBG_LOG << "boot_image_location parent_dir_name was " << parent_dir_name;
2573774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2583774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (GetInstructionSetFromString(parent_dir_name.c_str()) != kNone) {
2593774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          *error_msg = "Do not specify the architecture as part of the boot image location";
260c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe          return false;
2613774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
2623774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
2633774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2643774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      // Check that the boot image location points to a valid file name.
2653774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      std::string file_name;
2663774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (!LocationToFilename(boot_image_location, instruction_set_, &file_name)) {
2673774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        *error_msg = StringPrintf("No corresponding file for location '%s' exists",
2683774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                                  file_name.c_str());
269c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return false;
2703774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
2713774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2723774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      DBG_LOG << "boot_image_filename does exist: " << file_name;
2733774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
2743774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
275c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return true;
2763774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
2773774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2783774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  void PrintUsage() {
2793774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    fprintf(stderr, "%s", GetUsage().c_str());
2803774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
281c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe
282c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe protected:
283c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  virtual ParseStatus ParseCustom(const StringPiece& option ATTRIBUTE_UNUSED,
284c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe                                  std::string* error_msg ATTRIBUTE_UNUSED) {
285c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return kParseUnknownArgument;
286c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  }
287c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe
288c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  virtual ParseStatus ParseChecks(std::string* error_msg ATTRIBUTE_UNUSED) {
289c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return kParseOk;
290c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  }
2913774335b08076117d6950cd472cdd59a167470b5Igor Murashkin};
2923774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2933774335b08076117d6950cd472cdd59a167470b5Igor Murashkintemplate <typename Args = CmdlineArgs>
2943774335b08076117d6950cd472cdd59a167470b5Igor Murashkinstruct CmdlineMain {
2953774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  int Main(int argc, char** argv) {
2963774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    InitLogging(argv);
2973774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::unique_ptr<Args> args = std::unique_ptr<Args>(CreateArguments());
2983774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    args_ = args.get();
2993774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3003774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    DBG_LOG << "Try to parse";
3013774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3023774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (args_ == nullptr || !args_->Parse(argc, argv)) {
3033774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      return EXIT_FAILURE;
3043774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
3053774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3063774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    bool needs_runtime = NeedsRuntime();
307c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    std::unique_ptr<Runtime> runtime;
308c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe
3093774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3103774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (needs_runtime) {
311c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      std::string error_msg;
312c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      if (!args_->ParseCheckBootImage(&error_msg)) {
313c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        fprintf(stderr, "%s\n", error_msg.c_str());
314c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        args_->PrintUsage();
315c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return EXIT_FAILURE;
316c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      }
317c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      runtime.reset(CreateRuntime(args.get()));
318c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      if (runtime == nullptr) {
319c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return EXIT_FAILURE;
320c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      }
3213774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (!ExecuteWithRuntime(runtime.get())) {
3223774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        return EXIT_FAILURE;
3233774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
3243774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    } else {
3253774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (!ExecuteWithoutRuntime()) {
3263774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        return EXIT_FAILURE;
3273774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
3283774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
3293774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3303774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (!ExecuteCommon()) {
3313774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      return EXIT_FAILURE;
3323774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
3333774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3343774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return EXIT_SUCCESS;
3353774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3363774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3373774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Override this function to create your own arguments.
3383774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Usually will want to return a subtype of CmdlineArgs.
3393774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual Args* CreateArguments() {
3403774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return new Args();
3413774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3423774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3433774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Override this function to do something else with the runtime.
3443774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool ExecuteWithRuntime(Runtime* runtime) {
3453774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    CHECK(runtime != nullptr);
3463774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // Do nothing
3473774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3483774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3493774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3503774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Does the code execution need a runtime? Sometimes it doesn't.
3513774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool NeedsRuntime() {
3523774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3533774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3543774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3553774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Do execution without having created a runtime.
3563774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool ExecuteWithoutRuntime() {
3573774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3583774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3593774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3603774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Continue execution after ExecuteWith[out]Runtime
3613774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool ExecuteCommon() {
3623774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3633774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3643774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3653774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual ~CmdlineMain() {}
3663774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3673774335b08076117d6950cd472cdd59a167470b5Igor Murashkin protected:
3683774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  Args* args_ = nullptr;
3693774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3703774335b08076117d6950cd472cdd59a167470b5Igor Murashkin private:
371c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  Runtime* CreateRuntime(CmdlineArgs* args) {
3723774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    CHECK(args != nullptr);
3733774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
374c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return StartRuntime(args->boot_image_location_, args->instruction_set_);
3753774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3763774335b08076117d6950cd472cdd59a167470b5Igor Murashkin};
3773774335b08076117d6950cd472cdd59a167470b5Igor Murashkin}  // namespace art
3783774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3793774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#endif  // ART_CMDLINE_CMDLINE_H_
380