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