cmdline.h revision 57b34294758e9c00993913ebe43c7ee4698a5cc6
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
833774335b08076117d6950cd472cdd59a167470b5Igor Murashkinstatic Runtime* StartRuntime(const char* boot_image_location,
843774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                             InstructionSet instruction_set) {
853774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  CHECK(boot_image_location != nullptr);
863774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
873774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  RuntimeOptions options;
883774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
893774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // We are more like a compiler than a run-time. We don't want to execute code.
903774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  {
913774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    static NoopCompilerCallbacks callbacks;
923774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    options.push_back(std::make_pair("compilercallbacks", &callbacks));
933774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
943774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
953774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Boot image location.
963774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  {
973774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::string boot_image_option;
983774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    boot_image_option += "-Ximage:";
993774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    boot_image_option += boot_image_location;
1003774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    options.push_back(std::make_pair(boot_image_option.c_str(), nullptr));
1013774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
1023774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1033774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Instruction set.
1043774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  options.push_back(
1053774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      std::make_pair("imageinstructionset",
1063774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                     reinterpret_cast<const void*>(GetInstructionSetString(instruction_set))));
1073774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1083774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  if (!Runtime::Create(options, false)) {
1093774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    fprintf(stderr, "Failed to create runtime\n");
1103774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return nullptr;
1113774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
1123774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1133774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
1143774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // give it away now and then switch to a more manageable ScopedObjectAccess.
1153774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
1163774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1173774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  return Runtime::Current();
1183774335b08076117d6950cd472cdd59a167470b5Igor Murashkin}
1193774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1203774335b08076117d6950cd472cdd59a167470b5Igor Murashkinstruct CmdlineArgs {
1213774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  enum ParseStatus {
1223774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    kParseOk,               // Parse successful. Do not set the error message.
1233774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    kParseUnknownArgument,  // Unknown argument. Do not set the error message.
1243774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    kParseError,            // Parse ok, but failed elsewhere. Print the set error message.
1253774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  };
1263774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1273774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  bool Parse(int argc, char** argv) {
1283774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // Skip over argv[0].
1293774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    argv++;
1303774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    argc--;
1313774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1323774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (argc == 0) {
1333774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      fprintf(stderr, "No arguments specified\n");
1343774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      PrintUsage();
1353774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      return false;
1363774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
1373774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1383774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::string error_msg;
1393774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    for (int i = 0; i < argc; i++) {
1403774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      const StringPiece option(argv[i]);
1413774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (option.starts_with("--boot-image=")) {
1423774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        boot_image_location_ = option.substr(strlen("--boot-image=")).data();
1433774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      } else if (option.starts_with("--instruction-set=")) {
1443774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
1453774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        instruction_set_ = GetInstructionSetFromString(instruction_set_str.data());
1463774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (instruction_set_ == kNone) {
1473774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "Unsupported instruction set %s\n", instruction_set_str.data());
1483774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1493774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1503774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1513774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      } else if (option.starts_with("--output=")) {
1523774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        output_name_ = option.substr(strlen("--output=")).ToString();
1533774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        const char* filename = output_name_.c_str();
1543774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        out_.reset(new std::ofstream(filename));
1553774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (!out_->good()) {
1563774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "Failed to open output filename %s\n", filename);
1573774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1583774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1593774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1603774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        os_ = out_.get();
1613774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      } else {
1623774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        ParseStatus parse_status = ParseCustom(option, &error_msg);
1633774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1643774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (parse_status == kParseUnknownArgument) {
1653774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "Unknown argument %s\n", option.data());
1663774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1673774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1683774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (parse_status != kParseOk) {
1693774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "%s\n", error_msg.c_str());
1703774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1713774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1723774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
1733774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
1743774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
1753774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1763774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    DBG_LOG << "will call parse checks";
1773774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1783774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    {
1793774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      ParseStatus checks_status = ParseChecks(&error_msg);
1803774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (checks_status != kParseOk) {
1813774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          fprintf(stderr, "%s\n", error_msg.c_str());
1823774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          PrintUsage();
1833774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          return false;
1843774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
1853774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
1863774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1873774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
1883774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
1893774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1903774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual std::string GetUsage() const {
1913774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::string usage;
1923774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
1933774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    usage +=  // Required.
1943774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "  --boot-image=<file.art>: provide the image location for the boot class path.\n"
1953774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Do not include the arch as part of the name, it is added automatically.\n"
1963774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Example: --boot-image=/system/framework/boot.art\n"
1973774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "\n";
1983774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    usage += StringPrintf(  // Optional.
19957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe        "  --instruction-set=(arm|arm64|mips|mips64|x86|x86_64): for locating the image\n"
2003774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      file based on the image location set.\n"
2013774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Example: --instruction-set=x86\n"
2023774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Default: %s\n"
2033774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "\n",
2043774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        GetInstructionSetString(kRuntimeISA));
2053774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    usage +=  // Optional.
2063774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "  --output=<file> may be used to send the output to a file.\n"
2073774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "      Example: --output=/tmp/oatdump.txt\n"
2083774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        "\n";
2093774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2103774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return usage;
2113774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
2123774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2133774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Specified by --boot-image.
2143774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  const char* boot_image_location_ = nullptr;
2153774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Specified by --instruction-set.
2163774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  InstructionSet instruction_set_ = kRuntimeISA;
2173774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Specified by --output.
2183774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::ostream* os_ = &std::cout;
2193774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::unique_ptr<std::ofstream> out_;  // If something besides cout is used
2203774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  std::string output_name_;
2213774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2223774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual ~CmdlineArgs() {}
2233774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
224c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  bool ParseCheckBootImage(std::string* error_msg) {
2253774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (boot_image_location_ == nullptr) {
2263774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      *error_msg = "--boot-image must be specified";
227c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      return false;
2283774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
2293774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2303774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    DBG_LOG << "boot image location: " << boot_image_location_;
2313774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2323774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // Checks for --boot-image location.
2333774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    {
2343774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      std::string boot_image_location = boot_image_location_;
2353774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      size_t file_name_idx = boot_image_location.rfind("/");
2363774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (file_name_idx == std::string::npos) {  // Prevent a InsertIsaDirectory check failure.
2373774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        *error_msg = "Boot image location must have a / in it";
238c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return false;
2393774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
2403774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2413774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      // Don't let image locations with the 'arch' in it through, since it's not a location.
2423774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      // This prevents a common error "Could not create an image space..." when initing the Runtime.
2433774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (file_name_idx != std::string::npos) {
2443774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        std::string no_file_name = boot_image_location.substr(0, file_name_idx);
2453774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        size_t ancestor_dirs_idx = no_file_name.rfind("/");
2463774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2473774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        std::string parent_dir_name;
2483774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (ancestor_dirs_idx != std::string::npos) {
2493774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          parent_dir_name = no_file_name.substr(ancestor_dirs_idx + 1);
2503774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        } else {
2513774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          parent_dir_name = no_file_name;
2523774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
2533774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2543774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        DBG_LOG << "boot_image_location parent_dir_name was " << parent_dir_name;
2553774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2563774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        if (GetInstructionSetFromString(parent_dir_name.c_str()) != kNone) {
2573774335b08076117d6950cd472cdd59a167470b5Igor Murashkin          *error_msg = "Do not specify the architecture as part of the boot image location";
258c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe          return false;
2593774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        }
2603774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
2613774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2623774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      // Check that the boot image location points to a valid file name.
2633774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      std::string file_name;
2643774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (!LocationToFilename(boot_image_location, instruction_set_, &file_name)) {
2653774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        *error_msg = StringPrintf("No corresponding file for location '%s' exists",
2663774335b08076117d6950cd472cdd59a167470b5Igor Murashkin                                  file_name.c_str());
267c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return false;
2683774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
2693774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2703774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      DBG_LOG << "boot_image_filename does exist: " << file_name;
2713774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
2723774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
273c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return true;
2743774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
2753774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2763774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  void PrintUsage() {
2773774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    fprintf(stderr, "%s", GetUsage().c_str());
2783774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
279c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe
280c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe protected:
281c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  virtual ParseStatus ParseCustom(const StringPiece& option ATTRIBUTE_UNUSED,
282c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe                                  std::string* error_msg ATTRIBUTE_UNUSED) {
283c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return kParseUnknownArgument;
284c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  }
285c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe
286c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  virtual ParseStatus ParseChecks(std::string* error_msg ATTRIBUTE_UNUSED) {
287c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return kParseOk;
288c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  }
2893774335b08076117d6950cd472cdd59a167470b5Igor Murashkin};
2903774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2913774335b08076117d6950cd472cdd59a167470b5Igor Murashkintemplate <typename Args = CmdlineArgs>
2923774335b08076117d6950cd472cdd59a167470b5Igor Murashkinstruct CmdlineMain {
2933774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  int Main(int argc, char** argv) {
2943774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    InitLogging(argv);
2953774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    std::unique_ptr<Args> args = std::unique_ptr<Args>(CreateArguments());
2963774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    args_ = args.get();
2973774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
2983774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    DBG_LOG << "Try to parse";
2993774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3003774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (args_ == nullptr || !args_->Parse(argc, argv)) {
3013774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      return EXIT_FAILURE;
3023774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
3033774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3043774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    bool needs_runtime = NeedsRuntime();
305c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    std::unique_ptr<Runtime> runtime;
306c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe
3073774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3083774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (needs_runtime) {
309c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      std::string error_msg;
310c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      if (!args_->ParseCheckBootImage(&error_msg)) {
311c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        fprintf(stderr, "%s\n", error_msg.c_str());
312c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        args_->PrintUsage();
313c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return EXIT_FAILURE;
314c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      }
315c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      runtime.reset(CreateRuntime(args.get()));
316c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      if (runtime == nullptr) {
317c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe        return EXIT_FAILURE;
318c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe      }
3193774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (!ExecuteWithRuntime(runtime.get())) {
3203774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        return EXIT_FAILURE;
3213774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
3223774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    } else {
3233774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      if (!ExecuteWithoutRuntime()) {
3243774335b08076117d6950cd472cdd59a167470b5Igor Murashkin        return EXIT_FAILURE;
3253774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      }
3263774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
3273774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3283774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    if (!ExecuteCommon()) {
3293774335b08076117d6950cd472cdd59a167470b5Igor Murashkin      return EXIT_FAILURE;
3303774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    }
3313774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3323774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return EXIT_SUCCESS;
3333774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3343774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3353774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Override this function to create your own arguments.
3363774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Usually will want to return a subtype of CmdlineArgs.
3373774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual Args* CreateArguments() {
3383774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return new Args();
3393774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3403774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3413774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Override this function to do something else with the runtime.
3423774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool ExecuteWithRuntime(Runtime* runtime) {
3433774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    CHECK(runtime != nullptr);
3443774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    // Do nothing
3453774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3463774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3473774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3483774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Does the code execution need a runtime? Sometimes it doesn't.
3493774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool NeedsRuntime() {
3503774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3513774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3523774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3533774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Do execution without having created a runtime.
3543774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool ExecuteWithoutRuntime() {
3553774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3563774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3573774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3583774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  // Continue execution after ExecuteWith[out]Runtime
3593774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual bool ExecuteCommon() {
3603774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    return true;
3613774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3623774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3633774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  virtual ~CmdlineMain() {}
3643774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3653774335b08076117d6950cd472cdd59a167470b5Igor Murashkin protected:
3663774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  Args* args_ = nullptr;
3673774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3683774335b08076117d6950cd472cdd59a167470b5Igor Murashkin private:
369c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe  Runtime* CreateRuntime(CmdlineArgs* args) {
3703774335b08076117d6950cd472cdd59a167470b5Igor Murashkin    CHECK(args != nullptr);
3713774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
372c24f3990db5845691016b935df3d9382b6762f0fAndreas Gampe    return StartRuntime(args->boot_image_location_, args->instruction_set_);
3733774335b08076117d6950cd472cdd59a167470b5Igor Murashkin  }
3743774335b08076117d6950cd472cdd59a167470b5Igor Murashkin};
3753774335b08076117d6950cd472cdd59a167470b5Igor Murashkin}  // namespace art
3763774335b08076117d6950cd472cdd59a167470b5Igor Murashkin
3773774335b08076117d6950cd472cdd59a167470b5Igor Murashkin#endif  // ART_CMDLINE_CMDLINE_H_
378