diff options
Diffstat (limited to 'tools')
74 files changed, 1611 insertions, 781 deletions
diff --git a/tools/Android.bp b/tools/Android.bp index b7f5c1b08b..207a121848 100644 --- a/tools/Android.bp +++ b/tools/Android.bp @@ -37,6 +37,17 @@ soong_config_module_type_import { ], } +cc_binary { + name: "art_boot", + defaults: ["art_defaults"], + srcs: ["art_boot.cc"], + shared_libs: ["libbase"], + apex_available: [ + "com.android.art", + "com.android.art.debug", + ], +} + // Copy the art shell script to the host and target's bin directory art_module_sh_binary { name: "art-script", @@ -97,23 +108,3 @@ sh_binary { }, }, } - -python_binary_host { - name: "art-run-test-checker", - srcs: [ - "checker/**/*.py", - ], - main: "checker/checker.py", - version: { - py2: { - enabled: false, - }, - py3: { - enabled: true, - }, - }, - test_suites: [ - "general-tests", - "mts-art", - ], -} diff --git a/tools/PresubmitJsonLinter.java b/tools/PresubmitJsonLinter.java new file mode 100644 index 0000000000..334d20079d --- /dev/null +++ b/tools/PresubmitJsonLinter.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.google.gson.stream.JsonReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Pre upload hook that ensures art-buildbot expectation files (files under //art/tools ending with + * "_failures.txt", e.g. //art/tools/libcore_failures.txt) are well-formed json files. + * + * It makes basic validation of the keys but does not cover all the cases. Parser structure is + * based on external/vogar/src/vogar/ExpectationStore.java. + * + * Hook is set up in //art/PREUPLOAD.cfg See also //tools/repohooks/README.md + */ +class PresubmitJsonLinter { + + private static final int FLAGS = Pattern.MULTILINE | Pattern.DOTALL; + private static final Set<String> RESULTS = new HashSet<>(); + + static { + RESULTS.addAll(List.of( + "UNSUPPORTED", + "COMPILE_FAILED", + "EXEC_FAILED", + "EXEC_TIMEOUT", + "ERROR", + "SUCCESS" + )); + } + + public static void main(String[] args) { + for (String arg : args) { + info("Checking " + arg); + checkExpectationFile(arg); + } + } + + private static void info(String message) { + System.err.println(message); + } + + private static void error(String message) { + System.err.println(message); + System.exit(1); + } + + private static void checkExpectationFile(String arg) { + JsonReader reader; + try { + reader = new JsonReader(new FileReader(arg)); + } catch (FileNotFoundException e) { + error("File '" + arg + "' is not found"); + return; + } + reader.setLenient(true); + try { + reader.beginArray(); + while (reader.hasNext()) { + readExpectation(reader); + } + reader.endArray(); + } catch (IOException e) { + error("Malformed json: " + reader); + } + } + + private static void readExpectation(JsonReader reader) throws IOException { + Set<String> names = new LinkedHashSet<String>(); + Set<String> tags = new LinkedHashSet<String>(); + boolean readResult = false; + boolean readDescription = false; + + reader.beginObject(); + while (reader.hasNext()) { + String name = reader.nextName(); + switch (name) { + case "result": + String result = reader.nextString(); + if (!RESULTS.contains(result)) { + error("Invalid 'result' value: '" + result + + "'. Expected one of " + String.join(", ", RESULTS) + + ". " + reader); + } + readResult = true; + break; + case "substring": { + try { + Pattern.compile( + ".*" + Pattern.quote(reader.nextString()) + ".*", FLAGS); + } catch (PatternSyntaxException e) { + error("Malformed 'substring' value: " + reader); + } + } + case "pattern": { + try { + Pattern.compile(reader.nextString(), FLAGS); + } catch (PatternSyntaxException e) { + error("Malformed 'pattern' value: " + reader); + } + break; + } + case "failure": + names.add(reader.nextString()); + break; + case "description": + reader.nextString(); + readDescription = true; + break; + case "name": + names.add(reader.nextString()); + break; + case "names": + readStrings(reader, names); + break; + case "tags": + readStrings(reader, tags); + break; + case "bug": + reader.nextLong(); + break; + case "modes": + readModes(reader); + break; + case "modes_variants": + readModesAndVariants(reader); + break; + default: + error("Unknown key '" + name + "' in expectations file"); + reader.skipValue(); + break; + } + } + reader.endObject(); + + if (names.isEmpty()) { + error("Missing 'name' or 'failure' key in " + reader); + } + if (!readResult) { + error("Missing 'result' key in " + reader); + } + if (!readDescription) { + error("Missing 'description' key in " + reader); + } + } + + private static void readStrings(JsonReader reader, Set<String> output) throws IOException { + reader.beginArray(); + while (reader.hasNext()) { + output.add(reader.nextString()); + } + reader.endArray(); + } + + private static void readModes(JsonReader reader) throws IOException { + reader.beginArray(); + while (reader.hasNext()) { + reader.nextString(); + } + reader.endArray(); + } + + /** + * Expected format: mode_variants: [["host", "X32"], ["host", "X64"]] + */ + private static void readModesAndVariants(JsonReader reader) throws IOException { + reader.beginArray(); + while (reader.hasNext()) { + reader.beginArray(); + reader.nextString(); + reader.nextString(); + reader.endArray(); + } + reader.endArray(); + } +}
\ No newline at end of file diff --git a/tools/ahat/.clang-format b/tools/ahat/.clang-format new file mode 120000 index 0000000000..88ab38e627 --- /dev/null +++ b/tools/ahat/.clang-format @@ -0,0 +1 @@ +../../.clang-format-java-2
\ No newline at end of file diff --git a/tools/ahat/Android.bp b/tools/ahat/Android.bp index affa2e0585..5f6ba819fc 100644 --- a/tools/ahat/Android.bp +++ b/tools/ahat/Android.bp @@ -27,7 +27,7 @@ java_binary_host { visibility: [ "//libcore/metrictests/memory/host", ], - wrapper: "ahat", + wrapper: "ahat.sh", srcs: ["src/main/**/*.java"], manifest: "etc/ahat.mf", java_resources: ["etc/style.css"], diff --git a/tools/ahat/ahat b/tools/ahat/ahat.sh index 77c1d6e430..77c1d6e430 100755 --- a/tools/ahat/ahat +++ b/tools/ahat/ahat.sh diff --git a/tools/ahat/etc/style.css b/tools/ahat/etc/style.css index 47fae1d551..83e5b20c3c 100644 --- a/tools/ahat/etc/style.css +++ b/tools/ahat/etc/style.css @@ -14,6 +14,11 @@ * limitations under the License. */ +html { + /* Roboto has tabular numbers, use it if available, fallback to other sans. */ + font-family: "Roboto", "Arial", "sans-serif"; +} + div.menu { background-color: #eeffff; } @@ -39,3 +44,23 @@ table th { padding-left: 8px; padding-right: 8px; } + +.sidebar { + position: fixed; + right: 0; + top: 48px; + padding-left: 12px; + padding-right: 24px; + font-size: small; + border-left: 4px solid #dcedc8; +} + +.sidebar a { + text-decoration: none; + color: #4285f4; +} + +.sidebar a:hover { + text-decoration: underline; + color: #073042; +}
\ No newline at end of file diff --git a/tools/ahat/src/main/com/android/ahat/DocString.java b/tools/ahat/src/main/com/android/ahat/DocString.java index eda9b383c4..ca5dbf06ce 100644 --- a/tools/ahat/src/main/com/android/ahat/DocString.java +++ b/tools/ahat/src/main/com/android/ahat/DocString.java @@ -136,7 +136,7 @@ class DocString { if (isPlaceHolder) { string.append(DocString.removed("del")); } else if (size != 0) { - string.appendFormat("%,14d", size); + string.appendFormat("%,d", size); } return string; } @@ -162,13 +162,13 @@ class DocString { public DocString appendDelta(boolean noCurrent, boolean noBaseline, long current, long baseline) { if (noCurrent) { - append(removed(format("%+,14d", 0 - baseline))); + append(removed(format("%+,d", 0 - baseline))); } else if (noBaseline) { append(added("new")); } else if (current > baseline) { - append(added(format("%+,14d", current - baseline))); + append(added(format("%+,d", current - baseline))); } else if (current < baseline) { - append(removed(format("%+,14d", current - baseline))); + append(removed(format("%+,d", current - baseline))); } return this; } diff --git a/tools/ahat/src/main/com/android/ahat/HtmlDoc.java b/tools/ahat/src/main/com/android/ahat/HtmlDoc.java index d5106dc1dd..6c3ab2fe3e 100644 --- a/tools/ahat/src/main/com/android/ahat/HtmlDoc.java +++ b/tools/ahat/src/main/com/android/ahat/HtmlDoc.java @@ -18,6 +18,7 @@ package com.android.ahat; import java.io.PrintStream; import java.net.URI; +import java.util.ArrayList; import java.util.List; /** @@ -26,6 +27,7 @@ import java.util.List; class HtmlDoc implements Doc { private PrintStream ps; private Column[] mCurrentTableColumns; + private List<String> mSections; /** * Create an HtmlDoc that writes to the given print stream. @@ -34,6 +36,7 @@ class HtmlDoc implements Doc { */ public HtmlDoc(PrintStream ps, DocString title, URI style) { this.ps = ps; + mSections = new ArrayList<>(); ps.println("<!DOCTYPE html>"); ps.println("<html>"); @@ -59,9 +62,10 @@ class HtmlDoc implements Doc { @Override public void section(String title) { - ps.print("<h2>"); + ps.format("<h2 id=\"%d\">", mSections.size()); ps.print(DocString.text(title).html()); ps.println(":</h2>"); + mSections.add(title); } @Override @@ -182,8 +186,17 @@ class HtmlDoc implements Doc { mCurrentTableColumns = null; } + private void sidebar() { + ps.println("<div class=\"sidebar\">"); + for (int i = 0; i < mSections.size(); i++) { + ps.format("<p><a href=\"#%d\">%s</a></p>", i, mSections.get(i)); + } + ps.println("</div>"); + } + @Override public void close() { + sidebar(); ps.println("</body>"); ps.println("</html>"); ps.close(); diff --git a/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java b/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java index 81611b6c72..4cdbaf4270 100644 --- a/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java +++ b/tools/ahat/src/main/com/android/ahat/ObjectsHandler.java @@ -111,7 +111,7 @@ class ObjectsHandler implements AhatHandler { heapChoice.append(")"); doc.description(DocString.text("Heap"), heapChoice); - doc.description(DocString.text("Count"), DocString.format("%,14d", insts.size())); + doc.description(DocString.text("Count"), DocString.format("%,d", insts.size())); doc.end(); doc.println(DocString.text("")); diff --git a/tools/ahat/src/main/com/android/ahat/OverviewHandler.java b/tools/ahat/src/main/com/android/ahat/OverviewHandler.java index 5f0b473d1d..c6f4a54080 100644 --- a/tools/ahat/src/main/com/android/ahat/OverviewHandler.java +++ b/tools/ahat/src/main/com/android/ahat/OverviewHandler.java @@ -57,8 +57,6 @@ class OverviewHandler implements AhatHandler { doc.section("Bytes Retained by Heap"); printHeapSizes(doc); - - doc.big(Menu.getMenu()); } private void printHeapSizes(Doc doc) { diff --git a/tools/ahat/src/main/com/android/ahat/SiteHandler.java b/tools/ahat/src/main/com/android/ahat/SiteHandler.java index 5093f0d43e..671784efca 100644 --- a/tools/ahat/src/main/com/android/ahat/SiteHandler.java +++ b/tools/ahat/src/main/com/android/ahat/SiteHandler.java @@ -102,7 +102,7 @@ class SiteHandler implements AhatHandler { DocString.link( DocString.formattedUri("objects?id=%d&heap=%s&class=%s", site.getId(), info.heap.getName(), className), - DocString.format("%,14d", info.numInstances)), + DocString.format("%,d", info.numInstances)), DocString.delta(false, false, info.numInstances, baseinfo.numInstances), DocString.text(info.heap.getName()), Summarizer.summarize(info.classObj)); diff --git a/tools/ahat/src/test-dump/Main.java b/tools/ahat/src/test-dump/Main.java index 2e2907690d..711d66200c 100644 --- a/tools/ahat/src/test-dump/Main.java +++ b/tools/ahat/src/test-dump/Main.java @@ -43,6 +43,10 @@ public class Main { // Allocate the instance of DumpedStuff. stuff = new DumpedStuff(baseline); + // Preemptively garbage collect to avoid an inopportune GC triggering + // after this. + Runtime.getRuntime().gc(); + // Create a bunch of unreachable objects pointing to basicString for the // reverseReferencesAreNotUnreachable test for (int i = 0; i < 100; i++) { diff --git a/tools/ahat/src/test/com/android/ahat/InstanceTest.java b/tools/ahat/src/test/com/android/ahat/InstanceTest.java index 376122ba23..1f290304c0 100644 --- a/tools/ahat/src/test/com/android/ahat/InstanceTest.java +++ b/tools/ahat/src/test/com/android/ahat/InstanceTest.java @@ -224,6 +224,7 @@ public class InstanceTest { @Test public void reachability() throws IOException { TestDump dump = TestDump.getTestDump(); + // We were careful to avoid GC before dumping, so nothing here should be null. AhatInstance strong1 = dump.getDumpedAhatInstance("reachabilityReferenceChain"); AhatInstance soft1 = strong1.getField("referent").asAhatInstance(); AhatInstance strong2 = soft1.getField("referent").asAhatInstance(); diff --git a/tools/art_boot.cc b/tools/art_boot.cc new file mode 100644 index 0000000000..f725fc828e --- /dev/null +++ b/tools/art_boot.cc @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This binary is run on boot as a oneshot service. It should not be run at any +// other point. + +#include <string> + +#include "android-base/logging.h" +#include "android-base/properties.h" + +// Copies the value of one system property to another if it isn't empty and +// passes the predicate test_fn. +static void CopyPropertyIf(const char* src, const char* dst, bool (*test_fn)(const std::string&)) { + std::string prop = android::base::GetProperty(src, ""); + if (prop.empty()) { + LOG(INFO) << "Property " << src << " not set"; + } else if (!test_fn(prop)) { + LOG(INFO) << "Property " << src << " has ignored value " << prop; + } else { + if (android::base::SetProperty(dst, prop)) { + LOG(INFO) << "Set property " << dst << " to " << prop << " from " << src; + } else { + LOG(ERROR) << "Failed to set property " << dst << " to " << prop; + } + } +} + +int main(int, char** argv) { + android::base::InitLogging(argv); + + // Copy properties that must only be set at boot and not change value later. + // Note that P/H can change the properties in the experiment namespaces at any + // time. + CopyPropertyIf("persist.device_config.runtime_native_boot.useartservice", + "dalvik.vm.useartservice", + // If an OEM has set dalvik.vm.useartservice to false we + // shouldn't override it to true from the P/H property. + [](const std::string& prop) { return prop == "false"; }); + + return 0; +} diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc index 2f2562b973..e68d2ca3d5 100644 --- a/tools/art_verifier/art_verifier.cc +++ b/tools/art_verifier/art_verifier.cc @@ -42,11 +42,9 @@ namespace { bool LoadDexFile(const std::string& dex_filename, std::vector<std::unique_ptr<const DexFile>>* dex_files) { - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(dex_filename); std::string error_msg; - if (!dex_file_loader.Open(dex_filename.c_str(), - dex_filename.c_str(), - /* verify= */ true, + if (!dex_file_loader.Open(/* verify= */ true, /* verify_checksum= */ true, &error_msg, dex_files)) { diff --git a/tools/build_linux_bionic.sh b/tools/build_linux_bionic.sh index 8992512d57..bbe71b6f6f 100755 --- a/tools/build_linux_bionic.sh +++ b/tools/build_linux_bionic.sh @@ -16,83 +16,38 @@ # This will build a target using linux_bionic. It can be called with normal make # flags. -# -# TODO This runs a 'm clean' prior to building the targets in order to ensure -# that obsolete kati files don't mess up the build. -if [[ -z $ANDROID_BUILD_TOP ]]; then - pushd . -else - pushd $ANDROID_BUILD_TOP -fi +set -e if [ ! -d art ]; then echo "Script needs to be run at the root of the android tree" exit 1 fi +export TARGET_PRODUCT=linux_bionic + +# Avoid Soong error about invalid dependencies on disabled libLLVM_android, +# which we get due to the --soong-only mode. (Another variant is to set +# SOONG_ALLOW_MISSING_DEPENDENCIES). +export FORCE_BUILD_LLVM_COMPONENTS=true + # TODO(b/194433871): Set MODULE_BUILD_FROM_SOURCE to disable prebuilt modules, # which Soong otherwise can create duplicate install rules for in --soong-only # mode. -soong_args="MODULE_BUILD_FROM_SOURCE=true" +export MODULE_BUILD_FROM_SOURCE=true # Switch the build system to unbundled mode in the reduced manifest branch. if [ ! -d frameworks/base ]; then - soong_args="$soong_args TARGET_BUILD_UNBUNDLED=true" -fi - -source build/envsetup.sh >&/dev/null # for get_build_var -# Soong needs a bunch of variables set and will not run if they are missing. -# The default values of these variables is only contained in make, so use -# nothing to create the variables then remove all the other artifacts. -# Lunch since it seems we cannot find the build-number otherwise. -lunch aosp_x86-eng -build/soong/soong_ui.bash --make-mode $soong_args nothing - -if [ $? != 0 ]; then - exit 1 + export TARGET_BUILD_UNBUNDLED=true fi -out_dir=$(get_build_var OUT_DIR) -host_out=$(get_build_var HOST_OUT) - -# TODO(b/31559095) Figure out a better way to do this. -# -# There is no good way to force soong to generate host-bionic builds currently -# so this is a hacky workaround. -tmp_soong_var=$(mktemp --tmpdir soong.variables.bak.XXXXXX) -tmp_build_number=$(cat ${out_dir}/soong/build_number.txt) - -cat $out_dir/soong/soong.variables > ${tmp_soong_var} - -# See comment above about b/123645297 for why we cannot just do m clean. Clear -# out all files except for intermediates and installed files and dexpreopt.config. -find $out_dir/ -maxdepth 1 -mindepth 1 \ - -not -name soong \ - -not -name host \ - -not -name target | xargs -I '{}' rm -rf '{}' -find $out_dir/soong/ -maxdepth 1 -mindepth 1 \ - -not -name .intermediates \ - -not -name host \ - -not -name dexpreopt.config \ - -not -name target | xargs -I '{}' rm -rf '{}' - -python3 <<END - ${tmp_soong_var} ${out_dir}/soong/soong.variables -import json -import sys -x = json.load(open(sys.argv[1])) -x['Allow_missing_dependencies'] = True -x['HostArch'] = 'x86_64' -x['CrossHost'] = 'linux_bionic' -x['CrossHostArch'] = 'x86_64' -if 'CrossHostSecondaryArch' in x: - del x['CrossHostSecondaryArch'] -json.dump(x, open(sys.argv[2], mode='w')) -END - -rm $tmp_soong_var +vars="$(build/soong/soong_ui.bash --dumpvars-mode --vars="OUT_DIR BUILD_NUMBER")" +# Assign to a variable and eval that, since bash ignores any error status from +# the command substitution if it's directly on the eval line. +eval $vars -# Write a new build-number -echo ${tmp_build_number}_SOONG_ONLY_BUILD > ${out_dir}/soong/build_number.txt +# This file is currently not created in --soong-only mode, but some build +# targets depend on it. +printf %s "${BUILD_NUMBER}" > ${OUT_DIR}/soong/build_number.txt -build/soong/soong_ui.bash --make-mode --skip-config --soong-only $soong_args $@ +build/soong/soong_ui.bash --make-mode --soong-only "$@" diff --git a/tools/build_linux_bionic_tests.sh b/tools/build_linux_bionic_tests.sh index 7379e9a092..0470d6d24c 100755 --- a/tools/build_linux_bionic_tests.sh +++ b/tools/build_linux_bionic_tests.sh @@ -14,64 +14,36 @@ # See the License for the specific language governing permissions and # limitations under the License. - -if [[ -z $ANDROID_BUILD_TOP ]]; then - pushd . -else - pushd $ANDROID_BUILD_TOP -fi +set -e if [ ! -d art ]; then echo "Script needs to be run at the root of the android tree" exit 1 fi -soong_args="" - # Switch the build system to unbundled mode in the reduced manifest branch. if [ ! -d frameworks/base ]; then - soong_args="$soong_args TARGET_BUILD_UNBUNDLED=true" + export TARGET_BUILD_UNBUNDLED=true fi -source build/envsetup.sh >&/dev/null # for get_build_var - -out_dir=$(get_build_var OUT_DIR) -host_out=$(get_build_var HOST_OUT) - -# TODO(b/31559095) Figure out a better way to do this. -# -# There is no good way to force soong to generate host-bionic builds currently -# so this is a hacky workaround. +vars="$(build/soong/soong_ui.bash --dumpvars-mode --vars="OUT_DIR HOST_OUT")" +# Assign to a variable and eval that, since bash ignores any error status from +# the command substitution if it's directly on the eval line. +eval $vars # First build all the targets still in .mk files (also build normal glibc host # targets so we know what's needed to run the tests). -build/soong/soong_ui.bash --make-mode $soong_args "$@" test-art-host-run-test-dependencies build-art-host-tests -if [ $? != 0 ]; then - exit 1 -fi +build/soong/soong_ui.bash --make-mode "$@" test-art-host-run-test-dependencies build-art-host-tests -tmp_soong_var=$(mktemp --tmpdir soong.variables.bak.XXXXXX) +# Next build the Linux host Bionic targets in --soong-only mode. +export TARGET_PRODUCT=linux_bionic -echo "Saving soong.variables to " $tmp_soong_var -cat $out_dir/soong/soong.variables > ${tmp_soong_var} -python3 <<END - ${tmp_soong_var} ${out_dir}/soong/soong.variables -import json -import sys -x = json.load(open(sys.argv[1])) -x['Allow_missing_dependencies'] = True -x['HostArch'] = 'x86_64' -x['CrossHost'] = 'linux_bionic' -x['CrossHostArch'] = 'x86_64' -if 'CrossHostSecondaryArch' in x: - del x['CrossHostSecondaryArch'] -json.dump(x, open(sys.argv[2], mode='w')) -END -if [ $? != 0 ]; then - mv $tmp_soong_var $out_dir/soong/soong.variables - exit 2 -fi +# Avoid Soong error about invalid dependencies on disabled libLLVM_android, +# which we get due to the --soong-only mode. (Another variant is to set +# SOONG_ALLOW_MISSING_DEPENDENCIES). +export FORCE_BUILD_LLVM_COMPONENTS=true -soong_out=$out_dir/soong/host/linux_bionic-x86 +soong_out=$OUT_DIR/soong/host/linux_bionic-x86 declare -a bionic_targets # These are the binaries actually used in tests. Since some of the files are # java targets or 32 bit we cannot just do the same find for the bin files. @@ -89,24 +61,10 @@ bionic_targets=( $soong_out/bin/hprof-conv $soong_out/bin/signal_dumper $soong_out/lib64/libclang_rt.ubsan_standalone-x86_64-android.so - $(find $host_out/apex/com.android.art.host.zipapex -type f | sed "s:$host_out:$soong_out:g") - $(find $host_out/lib64 -type f | sed "s:$host_out:$soong_out:g") - $(find $host_out/nativetest64 -type f | sed "s:$host_out:$soong_out:g")) + $(find $HOST_OUT/apex/com.android.art.host.zipapex -type f | sed "s:$HOST_OUT:$soong_out:g") + $(find $HOST_OUT/lib64 -type f | sed "s:$HOST_OUT:$soong_out:g") + $(find $HOST_OUT/nativetest64 -type f | sed "s:$HOST_OUT:$soong_out:g")) echo building ${bionic_targets[*]} -build/soong/soong_ui.bash --make-mode --skip-config --soong-only $soong_args "$@" ${bionic_targets[*]} -ret=$? - -mv $tmp_soong_var $out_dir/soong/soong.variables - -# Having built with host-bionic confuses soong somewhat by making it think the -# linux_bionic targets are needed for art phony targets like -# test-art-host-run-test-dependencies. To work around this blow away all -# ninja files in OUT_DIR. The build system is smart enough to not need to -# rebuild stuff so this should be fine. -rm -f $OUT_DIR/*.ninja $OUT_DIR/soong/*.ninja - -popd - -exit $ret +build/soong/soong_ui.bash --make-mode --soong-only "$@" ${bionic_targets[*]} diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh index 48fc004506..cac98cb131 100755 --- a/tools/buildbot-build.sh +++ b/tools/buildbot-build.sh @@ -25,8 +25,6 @@ if [ ! -d art ]; then exit 1 fi -TARGET_ARCH=$(source build/envsetup.sh > /dev/null; get_build_var TARGET_ARCH) - # Logic for setting out_dir from build/make/core/envsetup.mk: if [[ -z $OUT_DIR ]]; then if [[ -z $OUT_DIR_COMMON_BASE ]]; then @@ -69,6 +67,9 @@ while true; do elif [[ "$1" == "--showcommands" ]]; then showcommands="showcommands" shift + elif [[ "$1" == "--dist" ]]; then + common_targets="$common_targets dist" + shift elif [[ "$1" == "" ]]; then break else @@ -83,11 +84,25 @@ if [[ $build_host == "no" ]] && [[ $build_target == "no" ]]; then build_target="yes" fi -# Allow to build successfully in master-art. -extra_args="SOONG_ALLOW_MISSING_DEPENDENCIES=true" +implementation_libs=( + "heapprofd_client_api" + "libandroid_runtime_lazy" + "libartpalette-system" + "libbinder" + "libbinder_ndk" + "libcutils" + "libutils" + "libvndksupport" +) -# Switch the build system to unbundled mode in the reduced manifest branch. -if [ ! -d frameworks/base ]; then +if [ -d frameworks/base ]; then + # In full manifest branches, build the implementation libraries from source + # instead of using prebuilts. + common_targets="$common_targets ${implementation_libs[*]}" +else + # Allow to build successfully in master-art. + extra_args="SOONG_ALLOW_MISSING_DEPENDENCIES=true BUILD_BROKEN_DISABLE_BAZEL=true" + # Switch the build system to unbundled mode in the reduced manifest branch. extra_args="$extra_args TARGET_BUILD_UNBUNDLED=true" fi @@ -120,13 +135,12 @@ if [[ $build_target == "yes" ]]; then # Indirect dependencies in the platform, e.g. through heapprofd_client_api. # These are built to go into system/lib(64) to be part of the system linker # namespace. - make_command+=" libbacktrace libnetd_client-target libprocinfo libtombstoned_client libunwindstack" + make_command+=" libnetd_client-target libprocinfo libtombstoned_client libunwindstack" # Stubs for other APEX SDKs, for use by vogar. Referenced from DEVICE_JARS in # external/vogar/src/vogar/ModeId.java. # Note these go into out/target/common/obj/JAVA_LIBRARIES which isn't removed # by "m installclean". make_command+=" i18n.module.public.api.stubs conscrypt.module.public.api.stubs" - make_command+=" ${ANDROID_PRODUCT_OUT#"${ANDROID_BUILD_TOP}/"}/system/etc/public.libraries.txt" # Targets required to generate a linker configuration for device within the # chroot environment. The *.libraries.txt targets are required by # the source linkerconfig but not included in the prebuilt one. @@ -166,6 +180,8 @@ if [[ $build_target == "yes" ]]; then # Extract prebuilt APEXes. debugfs=$ANDROID_HOST_OUT/bin/debugfs_static + fsckerofs=$ANDROID_HOST_OUT/bin/fsck.erofs + blkid=$ANDROID_HOST_OUT/bin/blkid_static for apex in ${apexes[@]}; do dir="$ANDROID_PRODUCT_OUT/system/apex/${apex}" apexbase="$ANDROID_PRODUCT_OUT/system/apex/${apex}" @@ -179,20 +195,16 @@ if [[ $build_target == "yes" ]]; then msginfo "Extracting APEX file:" "${file}" rm -rf $dir mkdir -p $dir - $ANDROID_HOST_OUT/bin/deapexer --debugfs_path $debugfs extract $file $dir + $ANDROID_HOST_OUT/bin/deapexer --debugfs_path $debugfs --fsckerofs_path $fsckerofs \ + --blkid_path $blkid extract $file $dir fi done - # Replace stub libraries with implemenation libraries: because we do chroot + # Replace stub libraries with implementation libraries: because we do chroot # testing, we need to install an implementation of the libraries (and cannot # rely on the one already installed on the device, if the device is post R and # has it). - implementation_libs=( - "heapprofd_client_api.so" - "libartpalette-system.so" - "liblog.so" - ) - if [ -d prebuilts/runtime/mainline/platform/impl ]; then + if [ -d prebuilts/runtime/mainline/platform/impl -a ! -d frameworks/base ]; then if [[ $TARGET_ARCH = arm* ]]; then arch32=arm arch64=arm64 @@ -200,18 +212,22 @@ if [[ $build_target == "yes" ]]; then arch32=x86 arch64=x86_64 fi - for so in ${implementation_libs[@]}; do - if [ -d "$ANDROID_PRODUCT_OUT/system/lib" ]; then - cmd="cp -p prebuilts/runtime/mainline/platform/impl/$arch32/$so $ANDROID_PRODUCT_OUT/system/lib/$so" - msginfo "Executing" "$cmd" - eval "$cmd" - fi - if [ -d "$ANDROID_PRODUCT_OUT/system/lib64" ]; then - cmd="cp -p prebuilts/runtime/mainline/platform/impl/$arch64/$so $ANDROID_PRODUCT_OUT/system/lib64/$so" - msginfo "Executing" "$cmd" - eval "$cmd" - fi - done + if [ "$TARGET_ARCH" = riscv64 ]; then + true # no 32-bit arch for RISC-V + else + for so in ${implementation_libs[@]}; do + if [ -d "$ANDROID_PRODUCT_OUT/system/lib" ]; then + cmd="cp -p prebuilts/runtime/mainline/platform/impl/$arch32/${so}.so $ANDROID_PRODUCT_OUT/system/lib/${so}.so" + msginfo "Executing" "$cmd" + eval "$cmd" + fi + if [ -d "$ANDROID_PRODUCT_OUT/system/lib64" ]; then + cmd="cp -p prebuilts/runtime/mainline/platform/impl/$arch64/${so}.so $ANDROID_PRODUCT_OUT/system/lib64/${so}.so" + msginfo "Executing" "$cmd" + eval "$cmd" + fi + done + fi fi # Create canonical name -> file name symlink in the symbol directory for the @@ -299,6 +315,11 @@ if [[ $build_target == "yes" ]]; then mkdir -p $linkerconfig_root/system cp -r $ANDROID_PRODUCT_OUT/system/etc $linkerconfig_root/system + # Use our smaller public.libraries.txt that contains only the public libraries + # pushed to the chroot directory. + cp $ANDROID_BUILD_TOP/art/tools/public.libraries.buildbot.txt \ + $linkerconfig_root/system/etc/public.libraries.txt + # For linkerconfig to pick up the APEXes correctly we need to make them # available in $linkerconfig_root/apex. mkdir -p $linkerconfig_root/apex diff --git a/tools/buildbot-cleanup-device.sh b/tools/buildbot-cleanup-device.sh index 7dee149129..7fd57b413e 100755 --- a/tools/buildbot-cleanup-device.sh +++ b/tools/buildbot-cleanup-device.sh @@ -16,7 +16,22 @@ . "$(dirname $0)/buildbot-utils.sh" -# Setup as root, as device cleanup requires it. +# Testing on a Linux VM requires special cleanup. +if [[ -n "$ART_TEST_ON_VM" ]]; then + [[ -d "$ART_TEST_VM_DIR" ]] || { msgfatal "no VM found in $ART_TEST_VM_DIR"; } + $ART_SSH_CMD "true" || { msgfatal "VM not responding (tried \"$ART_SSH_CMD true\""; } + $ART_SSH_CMD " + sudo umount $ART_TEST_CHROOT/proc + sudo umount $ART_TEST_CHROOT/sys + sudo umount $ART_TEST_CHROOT/dev + sudo umount $ART_TEST_CHROOT/bin + sudo umount $ART_TEST_CHROOT/lib + rm -rf $ART_TEST_CHROOT + " + exit 0 +fi + +# Regular Android device. Setup as root, as device cleanup requires it. adb root adb wait-for-device diff --git a/tools/buildbot-setup-device.sh b/tools/buildbot-setup-device.sh index ad2c59cea5..90d680b7d2 100755 --- a/tools/buildbot-setup-device.sh +++ b/tools/buildbot-setup-device.sh @@ -25,7 +25,39 @@ else verbose=false fi -# Setup as root, as some actions performed here require it. +# Testing on a Linux VM requires special setup. +if [[ -n "$ART_TEST_ON_VM" ]]; then + [[ -d "$ART_TEST_VM_DIR" ]] || { msgfatal "no VM found in $ART_TEST_VM_DIR"; } + $ART_SSH_CMD "true" || { msgerror "no VM (tried \"$ART_SSH_CMD true\""; } + $ART_SSH_CMD " + mkdir $ART_TEST_CHROOT + + mkdir $ART_TEST_CHROOT/apex + mkdir $ART_TEST_CHROOT/bin + mkdir $ART_TEST_CHROOT/data + mkdir $ART_TEST_CHROOT/data/local + mkdir $ART_TEST_CHROOT/data/local/tmp + mkdir $ART_TEST_CHROOT/dev + mkdir $ART_TEST_CHROOT/etc + mkdir $ART_TEST_CHROOT/lib + mkdir $ART_TEST_CHROOT/linkerconfig + mkdir $ART_TEST_CHROOT/proc + mkdir $ART_TEST_CHROOT/sys + mkdir $ART_TEST_CHROOT/system + mkdir $ART_TEST_CHROOT/tmp + + sudo mount -t proc /proc art-test-chroot/proc + sudo mount -t sysfs /sys art-test-chroot/sys + sudo mount --bind /dev art-test-chroot/dev + sudo mount --bind /bin art-test-chroot/bin + sudo mount --bind /lib art-test-chroot/lib + $ART_CHROOT_CMD echo \"Hello from chroot! I am \$(uname -a).\" + " + exit 0 +fi + +# Regular Android device. Setup as root, as some actions performed here require it. +adb version adb root adb wait-for-device @@ -36,7 +68,11 @@ msginfo "Date on device" adb shell date host_seconds_since_epoch=$(date -u +%s) -device_seconds_since_epoch=$(adb shell date -u +%s) + +# Get the device time in seconds, but filter the output as some +# devices emit CRLF at the end of the command which then breaks the +# time comparisons in this script (Hammerhead, MRA59G 2457013). +device_seconds_since_epoch=$(adb shell date -u +%s | tr -c -d '[:digit:]') abs_time_difference_in_seconds=$(expr $host_seconds_since_epoch - $device_seconds_since_epoch) if [ $abs_time_difference_in_seconds -lt 0 ]; then @@ -173,6 +209,8 @@ if [[ -n "$ART_TEST_CHROOT" ]]; then || adb shell mount -o bind /dev "$ART_TEST_CHROOT/dev" adb shell mount | grep -q "^devpts on $ART_TEST_CHROOT/dev/pts type devpts " \ || adb shell mount -o bind /dev/pts "$ART_TEST_CHROOT/dev/pts" + adb shell mount | grep -q " on $ART_TEST_CHROOT/dev/cpuset type cgroup " \ + || adb shell mount -o bind /dev/cpuset "$ART_TEST_CHROOT/dev/cpuset" # Create /apex directory in chroot. adb shell mkdir -p "$ART_TEST_CHROOT/apex" diff --git a/tools/buildbot-sync.sh b/tools/buildbot-sync.sh index 28dab0ce04..ef9ec8b3a0 100755 --- a/tools/buildbot-sync.sh +++ b/tools/buildbot-sync.sh @@ -20,27 +20,21 @@ set -e . "$(dirname $0)/buildbot-utils.sh" -# Setup as root, as some actions performed here require it. -adb root -adb wait-for-device - -if [[ -z "$ANDROID_BUILD_TOP" ]]; then - msgerror 'ANDROID_BUILD_TOP environment variable is empty; did you forget to run `lunch`?' - exit 1 -fi - -if [[ -z "$ANDROID_PRODUCT_OUT" ]]; then - msgerror 'ANDROID_PRODUCT_OUT environment variable is empty; did you forget to run `lunch`?' - exit 1 +if [[ -z "$ART_TEST_ON_VM" ]]; then + # Setup as root, as some actions performed here require it. + adb root + adb wait-for-device fi -if [[ -z "$ART_TEST_CHROOT" ]]; then - msgerror 'ART_TEST_CHROOT environment variable is empty; ' \ +if [[ -z "$ANDROID_BUILD_TOP" ]]; then + msgfatal 'ANDROID_BUILD_TOP environment variable is empty; did you forget to run `lunch`?' +elif [[ -z "$ANDROID_PRODUCT_OUT" ]]; then + msgfatal 'ANDROID_PRODUCT_OUT environment variable is empty; did you forget to run `lunch`?' +elif [[ -z "$ART_TEST_CHROOT" ]]; then + msgfatal 'ART_TEST_CHROOT environment variable is empty; ' \ 'please set it before running this script.' - exit 1 fi - # Sync relevant product directories # --------------------------------- @@ -53,23 +47,40 @@ fi continue fi msginfo "Syncing $dir directory..." - adb shell mkdir -p "$ART_TEST_CHROOT/$dir" - adb push $dir "$ART_TEST_CHROOT/$(dirname $dir)" + if [[ -n "$ART_TEST_ON_VM" ]]; then + $ART_RSYNC_CMD -R $dir "$ART_TEST_SSH_USER@$ART_TEST_SSH_HOST:$ART_TEST_CHROOT" + else + adb shell mkdir -p "$ART_TEST_CHROOT/$dir" + adb push $dir "$ART_TEST_CHROOT/$(dirname $dir)" + fi done ) # Overwrite the default public.libraries.txt file with a smaller one that # contains only the public libraries pushed to the chroot directory. -adb push "$ANDROID_BUILD_TOP/art/tools/public.libraries.buildbot.txt" \ - "$ART_TEST_CHROOT/system/etc/public.libraries.txt" +if [[ -n "$ART_TEST_ON_VM" ]]; then + $ART_RSYNC_CMD "$ANDROID_BUILD_TOP/art/tools/public.libraries.buildbot.txt" \ + "$ART_TEST_SSH_USER@$ART_TEST_SSH_HOST:$ART_TEST_CHROOT/system/etc/public.libraries.txt" +else + adb push "$ANDROID_BUILD_TOP/art/tools/public.libraries.buildbot.txt" \ + "$ART_TEST_CHROOT/system/etc/public.libraries.txt" +fi # Create the framework directory if it doesn't exist. Some gtests need it. -adb shell mkdir -p "$ART_TEST_CHROOT/system/framework" +if [[ -n "$ART_TEST_ON_VM" ]]; then + $ART_SSH_CMD "$ART_CHROOT_CMD mkdir -p $ART_TEST_CHROOT/system/framework" +else + adb shell mkdir -p "$ART_TEST_CHROOT/system/framework" +fi # APEX packages activation. # ------------------------- -adb shell mkdir -p "$ART_TEST_CHROOT/apex" +if [[ -n "$ART_TEST_ON_VM" ]]; then + $ART_SSH_CMD "$ART_CHROOT_CMD mkdir -p $ART_TEST_CHROOT/apex" +else + adb shell mkdir -p "$ART_TEST_CHROOT/apex" +fi # Manually "activate" the flattened APEX $1 by syncing it to /apex/$2 in the # chroot. $2 defaults to $1. @@ -95,12 +106,19 @@ activate_apex() { msginfo "Extracting APEX ${src_apex_file}..." mkdir -p $src_apex_path $ANDROID_HOST_OUT/bin/deapexer --debugfs_path $ANDROID_HOST_OUT/bin/debugfs_static \ + --fsckerofs_path $ANDROID_HOST_OUT/bin/fsck.erofs \ + --blkid_path $ANDROID_HOST_OUT/bin/blkid_static \ extract ${src_apex_file} $src_apex_path fi msginfo "Activating APEX ${src_apex} as ${dst_apex}..." - adb shell rm -rf "$ART_TEST_CHROOT/apex/${dst_apex}" - adb push $src_apex_path "$ART_TEST_CHROOT/apex/${dst_apex}" + if [[ -n "$ART_TEST_ON_VM" ]]; then + $ART_RSYNC_CMD $src_apex_path/* \ + "$ART_TEST_SSH_USER@$ART_TEST_SSH_HOST:$ART_TEST_CHROOT/apex/${dst_apex}" + else + adb shell rm -rf "$ART_TEST_CHROOT/apex/${dst_apex}" + adb push $src_apex_path "$ART_TEST_CHROOT/apex/${dst_apex}" + fi } # "Activate" the required APEX modules. @@ -111,19 +129,34 @@ activate_apex com.android.tzdata activate_apex com.android.conscrypt activate_apex com.android.os.statsd -# Generate primary boot images on device for testing. -for b in {32,64}; do - basename="generate-boot-image$b" - bin_on_host="$ANDROID_PRODUCT_OUT/system/bin/$basename" - bin_on_device="/data/local/tmp/$basename" - output_dir="/system/framework/art_boot_images" - if [ -f $bin_on_host ]; then - msginfo "Generating the primary boot image ($b-bit)..." - adb push "$bin_on_host" "$ART_TEST_CHROOT$bin_on_device" - adb shell mkdir -p "$ART_TEST_CHROOT$output_dir" - # `compiler-filter=speed-profile` is required because OatDumpTest checks the compiled code in - # the boot image. - adb shell chroot "$ART_TEST_CHROOT" \ - "$bin_on_device" --output-dir=$output_dir --compiler-filter=speed-profile - fi -done +if [[ "$TARGET_ARCH" = "riscv64" ]]; then + true # Skip boot image generation for RISC-V; it's not supported. +else + # Generate primary boot images on device for testing. + for b in {32,64}; do + basename="generate-boot-image$b" + bin_on_host="$ANDROID_PRODUCT_OUT/system/bin/$basename" + bin_on_device="/data/local/tmp/$basename" + output_dir="/system/framework/art_boot_images" + if [ -f $bin_on_host ]; then + msginfo "Generating the primary boot image ($b-bit)..." + if [[ -n "$ART_TEST_ON_VM" ]]; then + $ART_RSYNC_CMD "$bin_on_host" \ + "$ART_TEST_SSH_USER@$ART_TEST_SSH_HOST:$ART_TEST_CHROOT$bin_on_device" + $ART_SSH_CMD "mkdir -p $ART_TEST_CHROOT$output_dir" + else + adb push "$bin_on_host" "$ART_TEST_CHROOT$bin_on_device" + adb shell mkdir -p "$ART_TEST_CHROOT$output_dir" + fi + # `compiler-filter=speed-profile` is required because OatDumpTest checks the compiled code in + # the boot image. + if [[ -n "$ART_TEST_ON_VM" ]]; then + $ART_SSH_CMD \ + "$ART_CHROOT_CMD $bin_on_device --output-dir=$output_dir --compiler-filter=speed-profile" + else + adb shell chroot "$ART_TEST_CHROOT" \ + "$bin_on_device" --output-dir=$output_dir --compiler-filter=speed-profile + fi + fi + done +fi diff --git a/tools/buildbot-teardown-device.sh b/tools/buildbot-teardown-device.sh index 927e3c5421..e71dcbef0b 100755 --- a/tools/buildbot-teardown-device.sh +++ b/tools/buildbot-teardown-device.sh @@ -19,6 +19,8 @@ . "$(dirname $0)/buildbot-utils.sh" +[[ -n "$ART_TEST_ON_VM" ]] && exit 0 + # Setup as root, as some actions performed here require it. adb root adb wait-for-device @@ -79,7 +81,7 @@ if [[ -n "$ART_TEST_CHROOT" ]]; then local remove_dir=$3 local dir="$ART_TEST_CHROOT/$dir_in_chroot" adb shell test -d "$dir" \ - && adb shell mount | grep -q "^$fstype on $dir type $fstype " \ + && adb shell mount | grep -q " on $dir type $fstype " \ && if adb shell umount "$dir"; then $remove_dir && adb shell rmdir "$dir" else @@ -95,6 +97,7 @@ if [[ -n "$ART_TEST_CHROOT" ]]; then adb shell rm -rf "$ART_TEST_CHROOT/apex" # Remove /dev from chroot. + remove_filesystem_from_chroot dev/cpuset cgroup false remove_filesystem_from_chroot dev/pts devpts false remove_filesystem_from_chroot dev tmpfs true diff --git a/tools/buildbot-utils.sh b/tools/buildbot-utils.sh index 32ed234d90..6a0714dcd4 100755 --- a/tools/buildbot-utils.sh +++ b/tools/buildbot-utils.sh @@ -53,7 +53,43 @@ function msgerror() { echo -e "${boldred}Error: ${nc}${message}" } +function msgfatal() { + local message="$*" + echo -e "${boldred}Fatal: ${nc}${message}" + exit 1 +} + function msgnote() { local message="$*" echo -e "${boldcyan}Note: ${nc}${message}" } + +export TARGET_ARCH=$(build/soong/soong_ui.bash --dumpvar-mode TARGET_ARCH) + +# Do some checks and prepare environment for tests that run on Linux (not on Android). +if [[ -n "$ART_TEST_ON_VM" ]]; then + if [[ -z $ANDROID_BUILD_TOP ]]; then + msgfatal "ANDROID_BUILD_TOP is not set" + elif [[ -z "$ART_TEST_SSH_USER" ]]; then + msgfatal "ART_TEST_SSH_USER not set" + elif [[ -z "$ART_TEST_SSH_HOST" ]]; then + msgfatal "ART_TEST_SSH_HOST not set" + elif [[ -z "$ART_TEST_SSH_PORT" ]]; then + msgfatal "ART_TEST_SSH_PORT not set" + fi + + export ART_TEST_CHROOT="/home/$ART_TEST_SSH_USER/art-test-chroot" + export ART_CHROOT_CMD="unshare --user --map-root-user chroot art-test-chroot" + export ART_SSH_CMD="ssh -q -p $ART_TEST_SSH_PORT $ART_TEST_SSH_USER@$ART_TEST_SSH_HOST -o IdentityAgent=none" + export ART_SCP_CMD="scp -P $ART_TEST_SSH_PORT -p -r -o IdentityAgent=none" + export ART_RSYNC_CMD="rsync -az" + export RSYNC_RSH="ssh -p $ART_TEST_SSH_PORT -o IdentityAgent=none" # don't prefix with "ART_", rsync expects this name + + if [[ "$TARGET_ARCH" =~ ^(arm64|riscv64)$ ]]; then + export ART_TEST_VM_IMG="ubuntu-22.04-server-cloudimg-$TARGET_ARCH.img" + export ART_TEST_VM_DIR="$ANDROID_BUILD_TOP/vm/$TARGET_ARCH" + export ART_TEST_VM="$ART_TEST_VM_DIR/$ART_TEST_VM_IMG" + else + msgfatal "unexpected TARGET_ARCH=$TARGET_ARCH; expected one of {arm64,riscv64}" + fi +fi diff --git a/tools/buildbot-vm.sh b/tools/buildbot-vm.sh new file mode 100755 index 0000000000..9574c9f0a5 --- /dev/null +++ b/tools/buildbot-vm.sh @@ -0,0 +1,128 @@ +#! /bin/bash +# +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +ART_TEST_ON_VM=true . "$(dirname $0)/buildbot-utils.sh" + +known_actions="create|boot|setup-ssh|connect|quit" + +if [[ -z $ANDROID_BUILD_TOP ]]; then + msgfatal "ANDROID_BUILD_TOP is not set" +elif [[ ( $# -ne 1 ) || ! ( "$1" =~ ^($known_actions)$ ) ]]; then + msgfatal "usage: $0 <$known_actions>" +fi + +action="$1" + +get_stable_binary() { + mkdir tmp && cd tmp + wget "http://security.ubuntu.com/ubuntu/pool/main/$1" + 7z x "$(basename $1)" && zstd -d data.tar.zst && tar -xf data.tar + mv "$2" .. + cd .. && rm -rf tmp +} + +if [[ $action = create ]]; then +( + rm -rf "$ART_TEST_VM_DIR" + mkdir -p "$ART_TEST_VM_DIR" + cd "$ART_TEST_VM_DIR" + + # sudo apt install qemu-system-<arch> qemu-efi cloud-image-utils + + # Get the cloud image for Ubunty 22.04 (Jammy) + wget "http://cloud-images.ubuntu.com/releases/22.04/release/$ART_TEST_VM_IMG" + + if [[ "$TARGET_ARCH" = "riscv64" ]]; then + # Get U-Boot for Ubuntu 22.04 (Jammy) + get_stable_binary \ + u/u-boot/u-boot-qemu_2022.01+dfsg-2ubuntu2.3_all.deb \ + usr/lib/u-boot/qemu-riscv64_smode/uboot.elf + + # Get OpenSBI for Ubuntu 22.04 (Jammy) + get_stable_binary \ + o/opensbi/opensbi_1.1-0ubuntu0.22.04.1_all.deb \ + usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.elf + + elif [[ "$TARGET_ARCH" = "arm64" ]]; then + # Get EFI (ARM64) for Ubuntu 22.04 (Jammy) + get_stable_binary \ + e/edk2/qemu-efi-aarch64_2022.02-3ubuntu0.22.04.1_all.deb \ + usr/share/qemu-efi-aarch64/QEMU_EFI.fd + + dd if=/dev/zero of=flash0.img bs=1M count=64 + dd if=QEMU_EFI.fd of=flash0.img conv=notrunc + dd if=/dev/zero of=flash1.img bs=1M count=64 + fi + + qemu-img resize "$ART_TEST_VM_IMG" +128G + + # https://help.ubuntu.com/community/CloudInit + cat >user-data <<EOF +#cloud-config +ssh_pwauth: true +chpasswd: + expire: false + list: + - $ART_TEST_SSH_USER:ubuntu +EOF + cloud-localds user-data.img user-data +) +elif [[ $action = boot ]]; then +( + cd "$ART_TEST_VM_DIR" + if [[ "$TARGET_ARCH" = "riscv64" ]]; then + qemu-system-riscv64 \ + -m 16G \ + -smp 8 \ + -M virt \ + -nographic \ + -bios fw_jump.elf \ + -kernel uboot.elf \ + -drive file="$ART_TEST_VM_IMG",if=virtio \ + -drive file=user-data.img,format=raw,if=virtio \ + -device virtio-net-device,netdev=usernet \ + -netdev user,id=usernet,hostfwd=tcp::$ART_TEST_SSH_PORT-:22 + elif [[ "$TARGET_ARCH" = "arm64" ]]; then + qemu-system-aarch64 \ + -m 16G \ + -smp 8 \ + -cpu cortex-a57 \ + -M virt \ + -nographic \ + -drive if=none,file="$ART_TEST_VM_IMG",id=hd0 \ + -pflash flash0.img \ + -pflash flash1.img \ + -drive file=user-data.img,format=raw,id=cloud \ + -device virtio-blk-device,drive=hd0 \ + -device virtio-net-device,netdev=usernet \ + -netdev user,id=usernet,hostfwd=tcp::$ART_TEST_SSH_PORT-:22 + fi + +) +elif [[ $action = setup-ssh ]]; then + # Clean up mentions of this VM from known_hosts + sed -i -E "/\[$ART_TEST_SSH_HOST.*\]:$ART_TEST_SSH_PORT .*/d" $HOME/.ssh/known_hosts + ssh-copy-id -p "$ART_TEST_SSH_PORT" -o IdentityAgent=none "$ART_TEST_SSH_USER@$ART_TEST_SSH_HOST" + +elif [[ $action = connect ]]; then + $ART_SSH_CMD + +elif [[ $action = quit ]]; then + $ART_SSH_CMD "sudo poweroff" + +fi diff --git a/tools/check_presubmit_json_expectations.sh b/tools/check_presubmit_json_expectations.sh new file mode 100755 index 0000000000..ecb1e3e344 --- /dev/null +++ b/tools/check_presubmit_json_expectations.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# +# Copyright (C) 2022 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +REPO_ROOT="$1" + +FILES_TO_CHECK=() +for i in "${@:2}"; do + if [[ $i == *_failures.txt ]]; then + FILES_TO_CHECK+=($i) + fi +done + +# if no libcore_*_failures.txt files were changed +if [ ${#FILES_TO_CHECK[@]} -eq 0 ]; then + exit 0 +fi + +TMP_DIR=`mktemp -d` +# check if tmp dir was created +if [[ ! "$TMP_DIR" || ! -d "$TMP_DIR" ]]; then + echo "Could not create temp dir" + exit 1 +fi + +function cleanup { + rm -rf "$TMP_DIR" +} + +# register the cleanup function to be called on the EXIT signal +trap cleanup EXIT + +GSON_JAR="${REPO_ROOT}/external/caliper/lib/gson-2.2.2.jar" + +javac --class-path "$GSON_JAR" "${REPO_ROOT}/art/tools/PresubmitJsonLinter.java" -d "$TMP_DIR" +java --class-path "$TMP_DIR:$GSON_JAR" PresubmitJsonLinter "${FILES_TO_CHECK[@]}" diff --git a/tools/checker/Android.bp b/tools/checker/Android.bp new file mode 100644 index 0000000000..db2c597bf4 --- /dev/null +++ b/tools/checker/Android.bp @@ -0,0 +1,41 @@ +// +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "art_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["art_license"], +} + +python_binary_host { + name: "art-run-test-checker", + srcs: [ + "**/*.py", + ], + main: "checker.py", + version: { + py3: { + embedded_launcher: true, + }, + }, + test_suites: [ + "general-tests", + "mts-art", + ], +} diff --git a/tools/compile-jar.py b/tools/compile-jar.py index 56a07d5a61..d3484460ce 100755 --- a/tools/compile-jar.py +++ b/tools/compile-jar.py @@ -105,19 +105,17 @@ def get_bcp_runtime_args(additions, image, arch): "art/tools/host_bcp.sh", os.path.expandvars( "${{OUT}}/system/framework/oat/{}/services.odex".format(arch)), - "--use-first-dir" ] print("Running: {}".format(run_print(args))) print("=START=======================================") res = subprocess.run(args, capture_output=True, text=True) print("=END=========================================") if res.returncode != 0: - print("Falling back to com.android.art BCP") + print("Falling back to ART boot image: {}".format(res)) args = [ "art/tools/host_bcp.sh", os.path.expandvars( - "${{OUT}}/apex/com.android.art.debug/javalib/{}/boot.oat".format(arch)), - "--use-first-dir" + "${{OUT}}/apex/art_boot_images/javalib/{}/boot.oat".format(arch)), ] print("Running: {}".format(run_print(args))) print("=START=======================================") diff --git a/tools/cpp-define-generator/globals.def b/tools/cpp-define-generator/globals.def index 2572ea6f9b..459e5a8164 100644 --- a/tools/cpp-define-generator/globals.def +++ b/tools/cpp-define-generator/globals.def @@ -28,6 +28,7 @@ #include "mirror/object_reference.h" #include "runtime_globals.h" #include "stack.h" +#include "entrypoints/quick/callee_save_frame.h" #endif ASM_DEFINE(ACCESS_FLAGS_METHOD_IS_NATIVE, @@ -82,3 +83,11 @@ ASM_DEFINE(STD_MEMORY_ORDER_RELAXED, std::memory_order_relaxed) ASM_DEFINE(STACK_OVERFLOW_RESERVED_BYTES, GetStackOverflowReservedBytes(art::kRuntimeISA)) +ASM_DEFINE(CALLEE_SAVE_EVERYTHING_NUM_CORE_SPILLS, + art::POPCOUNT(art::RuntimeCalleeSaveFrame::GetCoreSpills( + art::CalleeSaveType::kSaveEverything))) +ASM_DEFINE(TAGGED_JNI_SP_MASK, art::ManagedStack::kTaggedJniSpMask) +ASM_DEFINE(TAGGED_JNI_SP_MASK_TOGGLED32, + ~static_cast<uint32_t>(art::ManagedStack::kTaggedJniSpMask)) +ASM_DEFINE(TAGGED_JNI_SP_MASK_TOGGLED64, + ~static_cast<uint64_t>(art::ManagedStack::kTaggedJniSpMask)) diff --git a/tools/cpp-define-generator/lockword.def b/tools/cpp-define-generator/lockword.def index a170c15f8b..5494d59d1d 100644 --- a/tools/cpp-define-generator/lockword.def +++ b/tools/cpp-define-generator/lockword.def @@ -30,10 +30,8 @@ ASM_DEFINE(LOCK_WORD_MARK_BIT_MASK_SHIFTED, art::LockWord::kMarkBitStateMaskShifted) ASM_DEFINE(LOCK_WORD_MARK_BIT_SHIFT, art::LockWord::kMarkBitStateShift) -ASM_DEFINE(LOCK_WORD_READ_BARRIER_STATE_MASK, +ASM_DEFINE(LOCK_WORD_READ_BARRIER_STATE_MASK_SHIFTED, art::LockWord::kReadBarrierStateMaskShifted) -ASM_DEFINE(LOCK_WORD_READ_BARRIER_STATE_MASK_TOGGLED, - art::LockWord::kReadBarrierStateMaskShiftedToggled) ASM_DEFINE(LOCK_WORD_READ_BARRIER_STATE_SHIFT, art::LockWord::kReadBarrierStateShift) ASM_DEFINE(LOCK_WORD_STATE_FORWARDING_ADDRESS, diff --git a/tools/cpp-define-generator/mirror_class.def b/tools/cpp-define-generator/mirror_class.def index 8cfd54e8d6..062a7aa4b7 100644 --- a/tools/cpp-define-generator/mirror_class.def +++ b/tools/cpp-define-generator/mirror_class.def @@ -16,6 +16,7 @@ #if ASM_DEFINE_INCLUDE_DEPENDENCIES #include "mirror/class.h" +#include "subtype_check.h" #endif ASM_DEFINE(MIRROR_CLASS_ACCESS_FLAGS_OFFSET, @@ -49,3 +50,17 @@ ASM_DEFINE(MIRROR_CLASS_SUPER_CLASS_OFFSET, ASM_DEFINE(MIRROR_CLASS_IS_INTERFACE_FLAG, art::kAccInterface) ASM_DEFINE(MIRROR_CLASS_IS_INTERFACE_FLAG_BIT, art::WhichPowerOf2(art::kAccInterface)) +ASM_DEFINE(MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET, + art::mirror::Class::StatusOffset().SizeValue() + + (art::SubtypeCheckBits::BitStructSizeOf() / art::kBitsPerByte)) +ASM_DEFINE(MIRROR_CLASS_IS_VISIBLY_INITIALIZED_VALUE, + art::enum_cast<uint32_t>(art::ClassStatus::kVisiblyInitialized) << + (art::SubtypeCheckBits::BitStructSizeOf() % art::kBitsPerByte)) +ASM_DEFINE(MIRROR_CLASS_IS_INITIALIZING_VALUE, + art::enum_cast<uint32_t>(art::ClassStatus::kInitializing) << + (art::SubtypeCheckBits::BitStructSizeOf() % art::kBitsPerByte)) +ASM_DEFINE(MIRROR_CLASS_IS_INITIALIZED_VALUE, + art::enum_cast<uint32_t>(art::ClassStatus::kInitialized) << + (art::SubtypeCheckBits::BitStructSizeOf() % art::kBitsPerByte)) +ASM_DEFINE(MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET, + art::mirror::Class::ClinitThreadIdOffset().Int32Value()) diff --git a/tools/cpp-define-generator/runtime.def b/tools/cpp-define-generator/runtime.def index 2a2e303ba2..fd6567d87e 100644 --- a/tools/cpp-define-generator/runtime.def +++ b/tools/cpp-define-generator/runtime.def @@ -30,3 +30,7 @@ ASM_DEFINE(RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET, art::Runtime::GetCalleeSaveMethodOffset(art::CalleeSaveType::kSaveRefsAndArgs)) ASM_DEFINE(RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET, art::Runtime::GetCalleeSaveMethodOffset(art::CalleeSaveType::kSaveRefsOnly)) +ASM_DEFINE(RUNTIME_INSTRUMENTATION_OFFSET, art::Runtime::GetInstrumentationOffset().Int32Value()) +ASM_DEFINE(RUN_EXIT_HOOKS_OFFSET_FROM_RUNTIME_INSTANCE, + art::Runtime::GetInstrumentationOffset().Int32Value() + + art::instrumentation::Instrumentation::RunExitHooksOffset().Int32Value()) diff --git a/tools/cpp-define-generator/thread.def b/tools/cpp-define-generator/thread.def index bae92009b2..97033fcaf2 100644 --- a/tools/cpp-define-generator/thread.def +++ b/tools/cpp-define-generator/thread.def @@ -37,6 +37,8 @@ ASM_DEFINE(THREAD_INTERPRETER_CACHE_SIZE_SHIFT, (art::WhichPowerOf2(sizeof(art::InterpreterCache::Entry)) - 2)) ASM_DEFINE(THREAD_IS_GC_MARKING_OFFSET, art::Thread::IsGcMarkingOffset<art::kRuntimePointerSize>().Int32Value()) +ASM_DEFINE(THREAD_DEOPT_CHECK_REQUIRED_OFFSET, + art::Thread::DeoptCheckRequiredOffset<art::kRuntimePointerSize>().Int32Value()) ASM_DEFINE(THREAD_LOCAL_ALLOC_STACK_END_OFFSET, art::Thread::ThreadLocalAllocStackEndOffset<art::kRuntimePointerSize>().Int32Value()) ASM_DEFINE(THREAD_LOCAL_ALLOC_STACK_TOP_OFFSET, @@ -69,3 +71,5 @@ ASM_DEFINE(THREAD_READ_BARRIER_MARK_REG00_OFFSET, art::Thread::ReadBarrierMarkEntryPointsOffset<art::kRuntimePointerSize>(0)) ASM_DEFINE(THREAD_SHARED_METHOD_HOTNESS_OFFSET, art::Thread::SharedMethodHotnessOffset<art::kRuntimePointerSize>().Int32Value()) +ASM_DEFINE(THREAD_TID_OFFSET, + art::Thread::TidOffset<art::kRuntimePointerSize>().Int32Value()) diff --git a/tools/dexanalyze/Android.bp b/tools/dexanalyze/Android.bp index 2a625d6e6b..5b875594cf 100644 --- a/tools/dexanalyze/Android.bp +++ b/tools/dexanalyze/Android.bp @@ -49,6 +49,7 @@ art_cc_binary { apex_available: [ "com.android.art", "com.android.art.debug", + "test_broken_com.android.art", ], } diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc index f0ce4c4607..79602aacbc 100644 --- a/tools/dexanalyze/dexanalyze.cc +++ b/tools/dexanalyze/dexanalyze.cc @@ -14,20 +14,21 @@ * limitations under the License. */ +#include <android-base/file.h> + #include <cstdint> #include <iostream> #include <set> #include <sstream> -#include <android-base/file.h> - -#include "dexanalyze_bytecode.h" -#include "dexanalyze_experiments.h" -#include "dexanalyze_strings.h" +#include "base/mem_map.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file.h" #include "dex/dex_file_loader.h" #include "dex/dex_instruction-inl.h" +#include "dexanalyze_bytecode.h" +#include "dexanalyze_experiments.h" +#include "dexanalyze_strings.h" namespace art { namespace dexanalyze { @@ -202,20 +203,18 @@ class DexAnalyze { for (const std::string& filename : options.filenames_) { std::string content; // TODO: once added, use an API to android::base to read a std::vector<uint8_t>. - if (!android::base::ReadFileToString(filename.c_str(), &content)) { + if (!android::base::ReadFileToString(filename, &content)) { LOG(ERROR) << "ReadFileToString failed for " + filename << std::endl; return kExitCodeFailedToOpenFile; } std::vector<std::unique_ptr<const DexFile>> dex_files; - const DexFileLoader dex_file_loader; - if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()), - content.size(), - filename.c_str(), - options.run_dex_file_verifier_, - options.verify_checksum_, - &error_code, - &error_msg, - &dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast<const uint8_t*>(content.data()), content.size(), filename); + if (!dex_file_loader.Open(options.run_dex_file_verifier_, + options.verify_checksum_, + &error_code, + &error_msg, + &dex_files)) { LOG(ERROR) << "OpenAll failed for " + filename << " with " << error_msg << std::endl; return kExitCodeFailedToOpenDex; } @@ -240,6 +239,7 @@ class DexAnalyze { } // namespace art int main(int argc, char** argv) { + art::MemMap::Init(); return art::dexanalyze::DexAnalyze::Run(argc, argv); } diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc index b124f433b3..384ab374cd 100644 --- a/tools/dexanalyze/dexanalyze_experiments.cc +++ b/tools/dexanalyze/dexanalyze_experiments.cc @@ -459,6 +459,7 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) { } // Count uses of top 16n. std::vector<size_t> uses; + uses.reserve(types_accessed.size()); for (auto&& p : types_accessed) { uses.push_back(p.second); } diff --git a/tools/dexanalyze/dexanalyze_test.cc b/tools/dexanalyze/dexanalyze_test.cc index 9e6ed6df67..474615dec2 100644 --- a/tools/dexanalyze/dexanalyze_test.cc +++ b/tools/dexanalyze/dexanalyze_test.cc @@ -14,12 +14,12 @@ * limitations under the License. */ -#include "common_runtime_test.h" +#include "base/common_art_test.h" #include "exec_utils.h" namespace art { -class DexAnalyzeTest : public CommonRuntimeTest { +class DexAnalyzeTest : public CommonArtTest { public: std::string GetDexAnalyzePath() { return GetArtBinDir() + "/dexanalyze"; diff --git a/tools/dexfuzz/.clang-format b/tools/dexfuzz/.clang-format new file mode 120000 index 0000000000..88ab38e627 --- /dev/null +++ b/tools/dexfuzz/.clang-format @@ -0,0 +1 @@ +../../.clang-format-java-2
\ No newline at end of file diff --git a/tools/dexfuzz/Android.bp b/tools/dexfuzz/Android.bp index 02bda0e25a..083ecd74a9 100644 --- a/tools/dexfuzz/Android.bp +++ b/tools/dexfuzz/Android.bp @@ -33,6 +33,6 @@ java_library_host { // --- dexfuzz script ---------------- sh_binary_host { name: "dexfuzz-script", - src: "dexfuzz", - filename_from_src: true, + src: "dexfuzz.sh", + filename: "dexfuzz", } diff --git a/tools/dexfuzz/dexfuzz b/tools/dexfuzz/dexfuzz.sh index cd47008d09..cd47008d09 100755 --- a/tools/dexfuzz/dexfuzz +++ b/tools/dexfuzz/dexfuzz.sh diff --git a/tools/dist_linux_bionic.sh b/tools/dist_linux_bionic.sh index 4c7ba1ca3f..f71031065e 100755 --- a/tools/dist_linux_bionic.sh +++ b/tools/dist_linux_bionic.sh @@ -19,12 +19,6 @@ set -e # Builds the given targets using linux-bionic and moves the output files to the # DIST_DIR. Takes normal make arguments. -if [[ -z $ANDROID_BUILD_TOP ]]; then - pushd . -else - pushd $ANDROID_BUILD_TOP -fi - if [[ -z $DIST_DIR ]]; then echo "DIST_DIR must be set!" exit 1 @@ -35,10 +29,12 @@ if [ ! -d art ]; then exit 1 fi -source build/envsetup.sh >&/dev/null # for get_build_var -out_dir=$(get_build_var OUT_DIR) +vars="$(build/soong/soong_ui.bash --dumpvars-mode --vars="OUT_DIR")" +# Assign to a variable and eval that, since bash ignores any error status from +# the command substitution if it's directly on the eval line. +eval $vars -./art/tools/build_linux_bionic.sh $@ +./art/tools/build_linux_bionic.sh "$@" mkdir -p $DIST_DIR -cp -R ${out_dir}/soong/host/* $DIST_DIR/ +cp -R ${OUT_DIR}/soong/host/* $DIST_DIR/ diff --git a/tools/dmtracedump/createtesttrace.cc b/tools/dmtracedump/createtesttrace.cc index 444cce4082..7bb5a7f9f1 100644 --- a/tools/dmtracedump/createtesttrace.cc +++ b/tools/dmtracedump/createtesttrace.cc @@ -22,6 +22,7 @@ #include <assert.h> #include <ctype.h> #include <errno.h> +#include <memory> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -114,7 +115,7 @@ char* strndup(const char* src, size_t len) { * 2 and increments by 2 for each line. */ void parseInputFile(const char* inputFileName) { - FILE* inputFp = fopen(inputFileName, "r"); + FILE* inputFp = fopen(inputFileName, "re"); if (inputFp == nullptr) { perror(inputFileName); exit(1); @@ -143,7 +144,7 @@ void parseInputFile(const char* inputFileName) { /* Add space for a sentinel record at the end */ numRecords += 1; records = new dataRecord[numRecords]; - stack* callStack = new stack[numThreads]; + std::unique_ptr<stack[]> callStack(new stack[numThreads]); for (int32_t ii = 0; ii < numThreads; ++ii) { callStack[ii].frames = nullptr; callStack[ii].indentLevel = 0; @@ -395,7 +396,7 @@ void writeDataRecords(FILE* dataFp) { } void writeTrace(const char* traceFileName) { - FILE* fp = fopen(traceFileName, "w"); + FILE* fp = fopen(traceFileName, "we"); if (fp == nullptr) { perror(traceFileName); exit(1); diff --git a/tools/dmtracedump/tracedump.cc b/tools/dmtracedump/tracedump.cc index 3cb737474f..3385f4ac84 100644 --- a/tools/dmtracedump/tracedump.cc +++ b/tools/dmtracedump/tracedump.cc @@ -1046,7 +1046,7 @@ void dumpTrace() { for (int32_t i = 0; i < MAX_THREADS; i++) traceData.depth[i] = 2; // adjust for return from start function - FILE* dataFp = fopen(gOptions.traceFileName, "rb"); + FILE* dataFp = fopen(gOptions.traceFileName, "rbe"); if (dataFp == nullptr) return; DataKeys* pKeys = parseKeys(dataFp, 1); @@ -1465,7 +1465,7 @@ void createInclusiveProfileGraphNew(DataKeys* dataKeys) { snprintf(path, FILENAME_MAX, "dot-%d-%d.dot", (int32_t)time(nullptr), rand()); } - FILE* file = fopen(path, "w+"); + FILE* file = fopen(path, "we+"); fprintf(file, "digraph g {\nnode [shape = record,height=.1];\n"); @@ -1490,10 +1490,8 @@ void printInclusiveProfile(MethodEntry** pMethods, int32_t numMethods, uint64_t char classBuf[HTML_BUFSIZE], methodBuf[HTML_BUFSIZE]; char signatureBuf[HTML_BUFSIZE]; char anchor_buf[80]; - const char* anchor_close = ""; anchor_buf[0] = 0; if (gOptions.outputHtml) { - anchor_close = "</a>"; printf("<a name=\"inclusive\"></a>\n"); printf("<hr>\n"); outputNavigationBar(); @@ -2035,7 +2033,7 @@ void printMethodProfiles(TraceData* traceData, uint64_t sumThreadTime) { DataKeys* parseDataKeys(TraceData* traceData, const char* traceFileName, uint64_t* threadTime) { MethodEntry* caller; - FILE* dataFp = fopen(traceFileName, "rb"); + FILE* dataFp = fopen(traceFileName, "rbe"); if (dataFp == nullptr) return nullptr; DataKeys* dataKeys = parseKeys(dataFp, 0); diff --git a/tools/external_oj_libjdwp_art_no_read_barrier_failures.txt b/tools/external_oj_libjdwp_art_no_read_barrier_failures.txt new file mode 100644 index 0000000000..920b611e43 --- /dev/null +++ b/tools/external_oj_libjdwp_art_no_read_barrier_failures.txt @@ -0,0 +1,9 @@ +/* + * This file contains expectations for ART's buildbot. The purpose of this file is + * to temporarily list failing tests and not break the bots. + * + * This file contains the expectations for the 'libjdwp-aot' and 'libjdwp-jit' + * test groups on the chromium buildbot running without read-barrier. + */ +[ +] diff --git a/tools/generate_cmake_lists.py b/tools/generate_cmake_lists.py index b19c2920f0..3fda0034b2 100755 --- a/tools/generate_cmake_lists.py +++ b/tools/generate_cmake_lists.py @@ -32,6 +32,7 @@ Steps to setup CLion. (Also, exclude projects that you don't bother about. This will make the indexing faster). """ +from __future__ import print_function import sys import os @@ -47,7 +48,7 @@ def get_android_build_top(): path_to_top = os.path.realpath(path_to_top) if not os.path.exists(os.path.join(path_to_top, 'build/envsetup.sh')): - print path_to_top + print(path_to_top) raise AssertionError("geneate_cmake_lists.py must be located inside an android source tree") return path_to_top diff --git a/tools/generate_operator_out.py b/tools/generate_operator_out.py index f1491d827f..f3de61c134 100755 --- a/tools/generate_operator_out.py +++ b/tools/generate_operator_out.py @@ -65,7 +65,7 @@ def ProcessFile(filename): continue # Is this the start or end of a namespace? - m = re.search(r'^namespace (\S+) \{', raw_line) + m = re.search(r'^namespace (\S+) (HIDDEN |EXPORT )?\{', raw_line) if m: namespaces.append(m.group(1)) continue diff --git a/tools/golem/build-target.sh b/tools/golem/build-target.sh index d8ec58b364..1ebd7c9544 100755 --- a/tools/golem/build-target.sh +++ b/tools/golem/build-target.sh @@ -269,6 +269,8 @@ if [[ $mode == "golem" ]]; then execute lunch "$lunch_target" # Golem uses master-art repository which is missing a lot of other libraries. setenv SOONG_ALLOW_MISSING_DEPENDENCIES true + # master-art cannot build with Bazel. + setenv BUILD_BROKEN_DISABLE_BAZEL true # Let the build system know we're not aiming to do a full platform build. if [ ! -d frameworks/base ]; then setenv TARGET_BUILD_UNBUNDLED true diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc index aee3f9acd3..5c750af4aa 100644 --- a/tools/hiddenapi/hiddenapi.cc +++ b/tools/hiddenapi/hiddenapi.cc @@ -16,14 +16,15 @@ #include <fstream> #include <iostream> +#include <iterator> #include <map> #include <set> #include <string> #include <string_view> +#include <vector> #include "android-base/stringprintf.h" #include "android-base/strings.h" - #include "base/bit_utils.h" #include "base/hiddenapi_flags.h" #include "base/mem_map.h" @@ -34,6 +35,7 @@ #include "dex/art_dex_file_loader.h" #include "dex/class_accessor-inl.h" #include "dex/dex_file-inl.h" +#include "dex/dex_file_structs.h" namespace art { namespace hiddenapi { @@ -244,8 +246,15 @@ class DexMember { class ClassPath final { public: - ClassPath(const std::vector<std::string>& dex_paths, bool open_writable, bool ignore_empty) { - OpenDexFiles(dex_paths, open_writable, ignore_empty); + ClassPath(const std::vector<std::string>& dex_paths, bool ignore_empty) { + OpenDexFiles(dex_paths, ignore_empty); + } + + template <typename Fn> + void ForEachDexClass(const DexFile* dex_file, Fn fn) { + for (ClassAccessor accessor : dex_file->GetClasses()) { + fn(DexClass(accessor)); + } } template<typename Fn> @@ -283,47 +292,18 @@ class ClassPath final { } private: - void OpenDexFiles(const std::vector<std::string>& dex_paths, - bool open_writable, - bool ignore_empty) { - ArtDexFileLoader dex_loader; + void OpenDexFiles(const std::vector<std::string>& dex_paths, bool ignore_empty) { std::string error_msg; - if (open_writable) { - for (const std::string& filename : dex_paths) { - File fd(filename.c_str(), O_RDWR, /* check_usage= */ false); - CHECK_NE(fd.Fd(), -1) << "Unable to open file '" << filename << "': " << strerror(errno); - - // Memory-map the dex file with MAP_SHARED flag so that changes in memory - // propagate to the underlying file. We run dex file verification as if - // the dex file was not in boot claass path to check basic assumptions, - // such as that at most one of public/private/protected flag is set. - // We do those checks here and skip them when loading the processed file - // into boot class path. - std::unique_ptr<const DexFile> dex_file(dex_loader.OpenDex(fd.Release(), - /* location= */ filename, - /* verify= */ true, - /* verify_checksum= */ true, - /* mmap_shared= */ true, - &error_msg)); - CHECK(dex_file.get() != nullptr) << "Open failed for '" << filename << "' " << error_msg; - CHECK(dex_file->IsStandardDexFile()) << "Expected a standard dex file '" << filename << "'"; - CHECK(dex_file->EnableWrite()) - << "Failed to enable write permission for '" << filename << "'"; - dex_files_.push_back(std::move(dex_file)); - } - } else { - for (const std::string& filename : dex_paths) { - bool success = dex_loader.Open(filename.c_str(), - /* location= */ filename, - /* verify= */ true, - /* verify_checksum= */ true, - &error_msg, - &dex_files_); - // If requested ignore a jar with no classes.dex files. - if (!success && ignore_empty && error_msg != "Entry not found") { - CHECK(success) << "Open failed for '" << filename << "' " << error_msg; - } + for (const std::string& filename : dex_paths) { + DexFileLoader dex_file_loader(filename); + bool success = dex_file_loader.Open(/* verify= */ true, + /* verify_checksum= */ true, + &error_msg, + &dex_files_); + // If requested ignore a jar with no classes.dex files. + if (!success && ignore_empty && error_msg != "Entry not found") { + CHECK(success) << "Open failed for '" << filename << "' " << error_msg; } } } @@ -669,215 +649,125 @@ class HiddenapiClassDataBuilder final { // Edits a dex file, inserting a new HiddenapiClassData section. class DexFileEditor final { public: - DexFileEditor(const DexFile& old_dex, const std::vector<uint8_t>& hiddenapi_class_data) - : old_dex_(old_dex), - hiddenapi_class_data_(hiddenapi_class_data), - loaded_dex_header_(nullptr), - loaded_dex_maplist_(nullptr) {} - - // Copies dex file into a backing data vector, appends the given HiddenapiClassData - // and updates the MapList. - void Encode() { + // Add dex file to copy to output (possibly several files for multi-dex). + void Add(const DexFile* dex, const std::vector<uint8_t>&& hiddenapi_data) { // We do not support non-standard dex encodings, e.g. compact dex. - CHECK(old_dex_.IsStandardDexFile()); - - // If there are no data to append, copy the old dex file and return. - if (hiddenapi_class_data_.empty()) { - AllocateMemory(old_dex_.Size()); - Append(old_dex_.Begin(), old_dex_.Size(), /* update_header= */ false); - return; - } - - // Find the old MapList, find its size. - const dex::MapList* old_map = old_dex_.GetMapList(); - CHECK_LT(old_map->size_, std::numeric_limits<uint32_t>::max()); - - // Compute the size of the new dex file. We append the HiddenapiClassData, - // one MapItem and possibly some padding to align the new MapList. - CHECK(IsAligned<kMapListAlignment>(old_dex_.Size())) - << "End of input dex file is not 4-byte aligned, possibly because its MapList is not " - << "at the end of the file."; - size_t size_delta = - RoundUp(hiddenapi_class_data_.size(), kMapListAlignment) + sizeof(dex::MapItem); - size_t new_size = old_dex_.Size() + size_delta; - AllocateMemory(new_size); - - // Copy the old dex file into the backing data vector. Load the copied - // dex file to obtain pointers to its header and MapList. - Append(old_dex_.Begin(), old_dex_.Size(), /* update_header= */ false); - ReloadDex(/* verify= */ false); - - // Truncate the new dex file before the old MapList. This assumes that - // the MapList is the last entry in the dex file. This is currently true - // for our tooling. - // TODO: Implement the general case by zero-ing the old MapList (turning - // it into padding. - RemoveOldMapList(); - - // Append HiddenapiClassData. - size_t payload_offset = AppendHiddenapiClassData(); - - // Wrute new MapList with an entry for HiddenapiClassData. - CreateMapListWithNewItem(payload_offset); - - // Check that the pre-computed size matches the actual size. - CHECK_EQ(offset_, new_size); - - // Reload to all data structures. - ReloadDex(/* verify= */ false); - - // Update the dex checksum. - UpdateChecksum(); - - // Run DexFileVerifier on the new dex file as a CHECK. - ReloadDex(/* verify= */ true); + CHECK(dex->IsStandardDexFile()); + inputs_.emplace_back(dex, std::move(hiddenapi_data)); } // Writes the edited dex file into a file. void WriteTo(const std::string& path) { - CHECK(!data_.empty()); + std::vector<uint8_t> output; + + // Copy the old dex files into the backing data vector. + size_t truncated_size = 0; + std::vector<size_t> header_offset; + for (size_t i = 0; i < inputs_.size(); i++) { + const DexFile* dex = inputs_[i].first; + header_offset.push_back(output.size()); + std::copy( + dex->Begin(), dex->Begin() + dex->GetHeader().file_size_, std::back_inserter(output)); + + // Clear the old map list (make it into padding). + const dex::MapList* map = dex->GetMapList(); + size_t map_off = dex->GetHeader().map_off_; + size_t map_size = sizeof(map->size_) + map->size_ * sizeof(map->list_[0]); + CHECK_LE(map_off, output.size()) << "Map list past the end of file"; + CHECK_EQ(map_size, output.size() - map_off) << "Map list expected at the end of file"; + std::fill_n(output.data() + map_off, map_size, 0); + truncated_size = output.size() - map_size; + } + output.resize(truncated_size); // Truncate last map list. + + // Append the hidden api data into the backing data vector. + std::vector<size_t> hiddenapi_offset; + for (size_t i = 0; i < inputs_.size(); i++) { + const std::vector<uint8_t>& hiddenapi_data = inputs_[i].second; + output.resize(RoundUp(output.size(), kHiddenapiClassDataAlignment)); // Align. + hiddenapi_offset.push_back(output.size()); + std::copy(hiddenapi_data.begin(), hiddenapi_data.end(), std::back_inserter(output)); + } + + // Update the dex headers and map lists. + for (size_t i = 0; i < inputs_.size(); i++) { + output.resize(RoundUp(output.size(), kMapListAlignment)); // Align. + + const DexFile* dex = inputs_[i].first; + const dex::MapList* map = dex->GetMapList(); + std::vector<dex::MapItem> items(map->list_, map->list_ + map->size_); + + // Check the header entry. + CHECK(!items.empty()); + CHECK_EQ(items[0].type_, DexFile::kDexTypeHeaderItem); + CHECK_EQ(items[0].offset_, header_offset[i]); + + // Check and remove the old map list entry (it does not have to be last). + auto is_map_list = [](auto it) { return it.type_ == DexFile::kDexTypeMapList; }; + auto it = std::find_if(items.begin(), items.end(), is_map_list); + CHECK(it != items.end()); + CHECK_EQ(it->offset_, dex->GetHeader().map_off_); + items.erase(it); + + // Write new map list. + if (!inputs_[i].second.empty()) { + uint32_t payload_offset = hiddenapi_offset[i]; + items.push_back(dex::MapItem{DexFile::kDexTypeHiddenapiClassData, 0, 1u, payload_offset}); + } + uint32_t map_offset = output.size(); + items.push_back(dex::MapItem{DexFile::kDexTypeMapList, 0, 1u, map_offset}); + uint32_t item_count = items.size(); + Append(&output, &item_count, 1); + Append(&output, items.data(), items.size()); + + // Update header. + uint8_t* begin = output.data() + header_offset[i]; + auto* header = reinterpret_cast<DexFile::Header*>(begin); + header->map_off_ = map_offset; + if (i + 1 < inputs_.size()) { + CHECK_EQ(header->file_size_, header_offset[i + 1] - header_offset[i]); + } else { + // Extend last dex file until the end of the file. + header->data_size_ = output.size() - header->data_off_; + header->file_size_ = output.size() - header_offset[i]; + } + header->checksum_ = DexFile::CalculateChecksum(begin, header->file_size_); + // TODO: We should also update the SHA1 signature. + } + + // Write the output file. + CHECK(!output.empty()); std::ofstream ofs(path.c_str(), std::ofstream::out | std::ofstream::binary); - ofs.write(reinterpret_cast<const char*>(data_.data()), data_.size()); + ofs.write(reinterpret_cast<const char*>(output.data()), output.size()); ofs.flush(); CHECK(ofs.good()); ofs.close(); + + ReloadDex(path.c_str()); } private: static constexpr size_t kMapListAlignment = 4u; static constexpr size_t kHiddenapiClassDataAlignment = 4u; - void ReloadDex(bool verify) { + void ReloadDex(const char* filename) { std::string error_msg; - DexFileLoader loader; - loaded_dex_ = loader.Open( - data_.data(), - data_.size(), - "test_location", - old_dex_.GetLocationChecksum(), - /* oat_dex_file= */ nullptr, - /* verify= */ verify, - /* verify_checksum= */ verify, - &error_msg); - if (loaded_dex_.get() == nullptr) { - LOG(FATAL) << "Failed to load edited dex file: " << error_msg; - UNREACHABLE(); - } - - // Load the location of header and map list before we start editing the file. - loaded_dex_header_ = const_cast<DexFile::Header*>(&loaded_dex_->GetHeader()); - loaded_dex_maplist_ = const_cast<dex::MapList*>(loaded_dex_->GetMapList()); - } - - DexFile::Header& GetHeader() const { - CHECK(loaded_dex_header_ != nullptr); - return *loaded_dex_header_; - } - - dex::MapList& GetMapList() const { - CHECK(loaded_dex_maplist_ != nullptr); - return *loaded_dex_maplist_; - } - - void AllocateMemory(size_t total_size) { - data_.clear(); - data_.resize(total_size); - CHECK(IsAligned<kMapListAlignment>(data_.data())); - CHECK(IsAligned<kHiddenapiClassDataAlignment>(data_.data())); - offset_ = 0; - } - - uint8_t* GetCurrentDataPtr() { - return data_.data() + offset_; - } - - void UpdateDataSize(off_t delta, bool update_header) { - offset_ += delta; - if (update_header) { - DexFile::Header& header = GetHeader(); - header.file_size_ += delta; - header.data_size_ += delta; - } - } - - template<typename T> - T* Append(const T* src, size_t len, bool update_header = true) { - CHECK_LE(offset_ + len, data_.size()); - uint8_t* dst = GetCurrentDataPtr(); - memcpy(dst, src, len); - UpdateDataSize(len, update_header); - return reinterpret_cast<T*>(dst); - } - - void InsertPadding(size_t alignment) { - size_t len = RoundUp(offset_, alignment) - offset_; - std::vector<uint8_t> padding(len, 0); - Append(padding.data(), padding.size()); - } - - void RemoveOldMapList() { - size_t map_size = GetMapList().Size(); - uint8_t* map_start = reinterpret_cast<uint8_t*>(&GetMapList()); - CHECK_EQ(map_start + map_size, GetCurrentDataPtr()) << "MapList not at the end of dex file"; - UpdateDataSize(-static_cast<off_t>(map_size), /* update_header= */ true); - CHECK_EQ(map_start, GetCurrentDataPtr()); - loaded_dex_maplist_ = nullptr; // do not use this map list any more - } - - void CreateMapListWithNewItem(size_t payload_offset) { - InsertPadding(/* alignment= */ kMapListAlignment); - - size_t new_map_offset = offset_; - dex::MapList* map = Append(old_dex_.GetMapList(), old_dex_.GetMapList()->Size()); - - // Check last map entry is a pointer to itself. - dex::MapItem& old_item = map->list_[map->size_ - 1]; - CHECK(old_item.type_ == DexFile::kDexTypeMapList); - CHECK_EQ(old_item.size_, 1u); - CHECK_EQ(old_item.offset_, GetHeader().map_off_); - - // Create a new MapItem entry with new MapList details. - dex::MapItem new_item; - new_item.type_ = old_item.type_; - new_item.unused_ = 0u; // initialize to ensure dex output is deterministic (b/119308882) - new_item.size_ = old_item.size_; - new_item.offset_ = new_map_offset; - - // Update pointer in the header. - GetHeader().map_off_ = new_map_offset; - - // Append a new MapItem and return its pointer. - map->size_++; - Append(&new_item, sizeof(dex::MapItem)); - - // Change penultimate entry to point to metadata. - old_item.type_ = DexFile::kDexTypeHiddenapiClassData; - old_item.size_ = 1u; // there is only one section - old_item.offset_ = payload_offset; - } - - size_t AppendHiddenapiClassData() { - size_t payload_offset = offset_; - CHECK_EQ(kMapListAlignment, kHiddenapiClassDataAlignment); - CHECK(IsAligned<kHiddenapiClassDataAlignment>(payload_offset)) - << "Should not need to align the section, previous data was already aligned"; - Append(hiddenapi_class_data_.data(), hiddenapi_class_data_.size()); - return payload_offset; + ArtDexFileLoader loader(filename); + std::vector<std::unique_ptr<const DexFile>> dex_files; + bool ok = loader.Open(/*verify*/ true, + /*verify_checksum*/ true, + &error_msg, + &dex_files); + CHECK(ok) << "Failed to load edited dex file: " << error_msg; } - void UpdateChecksum() { - GetHeader().checksum_ = loaded_dex_->CalculateChecksum(); + template <typename T> + void Append(std::vector<uint8_t>* output, const T* src, size_t len) { + const uint8_t* ptr = reinterpret_cast<const uint8_t*>(src); + std::copy(ptr, ptr + len * sizeof(T), std::back_inserter(*output)); } - const DexFile& old_dex_; - const std::vector<uint8_t>& hiddenapi_class_data_; - - std::vector<uint8_t> data_; - size_t offset_; - - std::unique_ptr<const DexFile> loaded_dex_; - DexFile::Header* loaded_dex_header_; - dex::MapList* loaded_dex_maplist_; + std::vector<std::pair<const DexFile*, const std::vector<uint8_t>>> inputs_; }; class HiddenApi final { @@ -991,48 +881,41 @@ class HiddenApi final { const std::string& input_path = boot_dex_paths_[i]; const std::string& output_path = output_dex_paths_[i]; - ClassPath boot_classpath({ input_path }, - /* open_writable= */ false, - /* ignore_empty= */ false); - std::vector<const DexFile*> input_dex_files = boot_classpath.GetDexFiles(); - CHECK_EQ(input_dex_files.size(), 1u); - const DexFile& input_dex = *input_dex_files[0]; - - HiddenapiClassDataBuilder builder(input_dex); - boot_classpath.ForEachDexClass([&](const DexClass& boot_class) { - builder.BeginClassDef(boot_class.GetClassDefIndex()); - if (boot_class.GetData() != nullptr) { - auto fn_shared = [&](const DexMember& boot_member) { - auto signature = boot_member.GetApiEntry(); - auto it = api_list.find(signature); - bool api_list_found = (it != api_list.end()); - CHECK(!force_assign_all_ || api_list_found) - << "Could not find hiddenapi flags for dex entry: " << signature; - if (api_list_found && it->second.GetIntValue() > max_hiddenapi_level_.GetIntValue()) { - ApiList without_domain(it->second.GetIntValue()); - LOG(ERROR) << "Hidden api flag " << without_domain - << " for member " << signature - << " in " << input_path - << " exceeds maximum allowable flag " - << max_hiddenapi_level_; - max_hiddenapi_level_error = true; - } else { - builder.WriteFlags(api_list_found ? it->second : ApiList::Sdk()); - } - }; - auto fn_field = [&](const ClassAccessor::Field& boot_field) { - fn_shared(DexMember(boot_class, boot_field)); - }; - auto fn_method = [&](const ClassAccessor::Method& boot_method) { - fn_shared(DexMember(boot_class, boot_method)); - }; - boot_class.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method); - } - builder.EndClassDef(boot_class.GetClassDefIndex()); - }); - - DexFileEditor dex_editor(input_dex, builder.GetData()); - dex_editor.Encode(); + ClassPath boot_classpath({input_path}, /* ignore_empty= */ false); + DexFileEditor dex_editor; + for (const DexFile* input_dex : boot_classpath.GetDexFiles()) { + HiddenapiClassDataBuilder builder(*input_dex); + boot_classpath.ForEachDexClass(input_dex, [&](const DexClass& boot_class) { + builder.BeginClassDef(boot_class.GetClassDefIndex()); + if (boot_class.GetData() != nullptr) { + auto fn_shared = [&](const DexMember& boot_member) { + auto signature = boot_member.GetApiEntry(); + auto it = api_list.find(signature); + bool api_list_found = (it != api_list.end()); + CHECK(!force_assign_all_ || api_list_found) + << "Could not find hiddenapi flags for dex entry: " << signature; + if (api_list_found && it->second.GetIntValue() > max_hiddenapi_level_.GetIntValue()) { + ApiList without_domain(it->second.GetIntValue()); + LOG(ERROR) << "Hidden api flag " << without_domain << " for member " << signature + << " in " << input_path << " exceeds maximum allowable flag " + << max_hiddenapi_level_; + max_hiddenapi_level_error = true; + } else { + builder.WriteFlags(api_list_found ? it->second : ApiList::Sdk()); + } + }; + auto fn_field = [&](const ClassAccessor::Field& boot_field) { + fn_shared(DexMember(boot_class, boot_field)); + }; + auto fn_method = [&](const ClassAccessor::Method& boot_method) { + fn_shared(DexMember(boot_class, boot_method)); + }; + boot_class.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method); + } + builder.EndClassDef(boot_class.GetClassDefIndex()); + }); + dex_editor.Add(input_dex, std::move(builder.GetData())); + } dex_editor.WriteTo(output_path); } @@ -1057,6 +940,7 @@ class HiddenApi final { std::map<std::string, ApiList> api_flag_map; size_t line_number = 1; + bool errors = false; for (std::string line; std::getline(api_file, line); line_number++) { // Every line contains a comma separated list with the signature as the // first element and the api flags as the rest @@ -1074,13 +958,21 @@ class HiddenApi final { std::vector<std::string>::iterator apiListBegin = values.begin() + 1; std::vector<std::string>::iterator apiListEnd = values.end(); bool success = ApiList::FromNames(apiListBegin, apiListEnd, &membership); - CHECK(success) << path << ":" << line_number - << ": Some flags were not recognized: " << line << kErrorHelp; - CHECK(membership.IsValid()) << path << ":" << line_number - << ": Invalid combination of flags: " << line << kErrorHelp; + if (!success) { + LOG(ERROR) << path << ":" << line_number + << ": Some flags were not recognized: " << line << kErrorHelp; + errors = true; + continue; + } else if (!membership.IsValid()) { + LOG(ERROR) << path << ":" << line_number + << ": Invalid combination of flags: " << line << kErrorHelp; + errors = true; + continue; + } api_flag_map.emplace(signature, membership); } + CHECK(!errors) << "Errors encountered while parsing file " << path; api_file.close(); return api_flag_map; @@ -1107,9 +999,7 @@ class HiddenApi final { std::set<std::string> unresolved; // Open all dex files. - ClassPath boot_classpath(boot_dex_paths_, - /* open_writable= */ false, - /* ignore_empty= */ false); + ClassPath boot_classpath(boot_dex_paths_, /* ignore_empty= */ false); Hierarchy boot_hierarchy(boot_classpath, fragment_, verbose_); // Mark all boot dex members private. @@ -1118,9 +1008,7 @@ class HiddenApi final { }); // Open all dependency API stub dex files. - ClassPath dependency_classpath(dependency_stub_dex_paths_, - /* open_writable= */ false, - /* ignore_empty= */ false); + ClassPath dependency_classpath(dependency_stub_dex_paths_, /* ignore_empty= */ false); // Mark all dependency API stub dex members as coming from the dependency. dependency_classpath.ForEachDexMember([&](const DexMember& boot_member) { @@ -1132,9 +1020,7 @@ class HiddenApi final { // Ignore any empty stub jars as it just means that they provide no APIs // for the current kind, e.g. framework-sdkextensions does not provide // any public APIs. - ClassPath stub_classpath(android::base::Split(cp_entry.first, ":"), - /* open_writable= */ false, - /* ignore_empty= */ true); + ClassPath stub_classpath(android::base::Split(cp_entry.first, ":"), /*ignore_empty=*/true); Hierarchy stub_hierarchy(stub_classpath, fragment_, verbose_); const ApiStubs::Kind stub_api = cp_entry.second; diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc index 3a0e62586d..36e80c5c23 100644 --- a/tools/hiddenapi/hiddenapi_test.cc +++ b/tools/hiddenapi/hiddenapi_test.cc @@ -106,7 +106,6 @@ class HiddenApiTest : public CommonRuntimeTest { } std::unique_ptr<const DexFile> OpenDex(const ScratchFile& file) { - ArtDexFileLoader dex_loader; std::string error_msg; File fd(file.GetFilename(), O_RDONLY, /* check_usage= */ false); @@ -115,9 +114,9 @@ class HiddenApiTest : public CommonRuntimeTest { UNREACHABLE(); } - std::unique_ptr<const DexFile> dex_file(dex_loader.OpenDex( - fd.Release(), /* location= */ file.GetFilename(), /* verify= */ true, - /* verify_checksum= */ true, /* mmap_shared= */ false, &error_msg)); + ArtDexFileLoader dex_loader(fd.Release(), file.GetFilename()); + std::unique_ptr<const DexFile> dex_file(dex_loader.Open( + /* verify= */ true, /* verify_checksum= */ true, /* mmap_shared= */ false, &error_msg)); if (dex_file.get() == nullptr) { LOG(FATAL) << "Open failed for '" << file.GetFilename() << "' " << error_msg; UNREACHABLE(); @@ -143,7 +142,7 @@ class HiddenApiTest : public CommonRuntimeTest { std::map<std::string, std::string> flags; for (std::string line; std::getline(ifs, line);) { - std::size_t comma = line.find(","); + std::size_t comma = line.find(','); if (comma == std::string::npos) { flags.emplace(line, ""); } else { diff --git a/tools/host_bcp.sh b/tools/host_bcp.sh index 26231cdca1..62ebae70d7 100755 --- a/tools/host_bcp.sh +++ b/tools/host_bcp.sh @@ -14,27 +14,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -if [[ ${#@} != 1 ]] && [[ ${#@} != 2 ]]; then +if [[ ${#@} != 1 ]]; then cat <<EOF Usage - host_bcp <image> [--use-first-dir] | xargs <art-host-tool> ... + host_bcp <image> | xargs <art-host-tool> ... Extracts boot class path locations from <image> and outputs the appropriate --runtime-arg -Xbootclasspath:... --runtime-arg -Xbootclasspath-locations:... arguments for many ART host tools based on the \$ANDROID_PRODUCT_OUT variable -and existing \$ANDROID_PRODUCT_OUT/apex/com.android.art* paths. -If --use-first-dir is specified, the script will use the first apex dir instead -of resulting in an error. +and existing \$ANDROID_PRODUCT_OUT/apex/* paths. EOF exit 1 fi IMAGE=$1 -USE_FIRST_DIR=false - -if [[ $2 == "--use-first-dir" ]]; then - USE_FIRST_DIR=true -fi if [[ ! -e ${IMAGE} ]]; then IMAGE=${ANDROID_PRODUCT_OUT}/$1 @@ -50,34 +43,33 @@ if [[ "x${BCPL}" == "x" ]]; then exit 1 fi -MANIFEST=/apex_manifest.pb -ART_APEX=/apex/com.android.art -ART_APEX_SELECTED= -for m in `ls -1 -d ${ANDROID_PRODUCT_OUT}{,/system}${ART_APEX}*${MANIFEST} 2>/dev/null`; do - d=${m:0:-${#MANIFEST}} - if [[ "x${ART_APEX_SELECTED}" != "x" ]]; then - if [[ $USE_FIRST_DIR == true ]]; then - break - fi - echo "Multiple ART APEX dirs: ${ART_APEX_SELECTED}, ${d}." - exit 1 - fi - ART_APEX_SELECTED=${d} -done -if [[ "x${ART_APEX_SELECTED}" == "x" ]]; then - echo "No ART APEX dir." +APEX_INFO_LIST=${ANDROID_PRODUCT_OUT}/apex/apex-info-list.xml +if [[ ! -e ${APEX_INFO_LIST} ]]; then + echo "Failed to locate apex info at ${APEX_INFO_LIST}." exit 1 fi BCP= OLD_IFS=${IFS} IFS=: +APEX_PREFIX=/apex/ for COMPONENT in ${BCPL}; do HEAD=${ANDROID_PRODUCT_OUT} TAIL=${COMPONENT} - if [[ ${COMPONENT:0:${#ART_APEX}} = ${ART_APEX} ]]; then - HEAD=${ART_APEX_SELECTED} - TAIL=${COMPONENT:${#ART_APEX}} + # Apex module paths aren't symlinked on the host, so map from the symbolic + # device path to the prebuilt (host) module path using the apex info table. + if [[ ${COMPONENT:0:${#APEX_PREFIX}} = ${APEX_PREFIX} ]]; then + # First extract the symbolic module name and its (internal) jar path. + COMPONENT=${COMPONENT#${APEX_PREFIX}} + MODULE_NAME=${COMPONENT%%/*} + MODULE_JAR=${COMPONENT#*/} + # Use the module name to look up the preinstalled module path.. + HOST_MODULE=`xmllint --xpath "string(//apex-info[@moduleName=\"${MODULE_NAME}\"]/@preinstalledModulePath)" ${APEX_INFO_LIST}` + # Extract the preinstalled module name from the full path (strip prefix/suffix). + HOST_MODULE_NAME=${HOST_MODULE#*${APEX_PREFIX}} + HOST_MODULE_NAME=${HOST_MODULE_NAME%.*apex} + # Rebuild the host path using the preinstalled module name. + TAIL="${APEX_PREFIX}${HOST_MODULE_NAME}/${MODULE_JAR}" fi if [[ ! -e $HEAD$TAIL ]]; then echo "File does not exist: $HEAD$TAIL" diff --git a/tools/jvmti-agents/chain-agents/chainagents.cc b/tools/jvmti-agents/chain-agents/chainagents.cc index 1242409bdf..d272fc120a 100644 --- a/tools/jvmti-agents/chain-agents/chainagents.cc +++ b/tools/jvmti-agents/chain-agents/chainagents.cc @@ -53,7 +53,7 @@ enum class StartType { OnLoad, }; -static std::pair<std::string, std::string> Split(std::string source, char delim) { +static std::pair<std::string, std::string> Split(const std::string& source, char delim) { std::string first(source.substr(0, source.find(delim))); if (source.find(delim) == std::string::npos) { return std::pair(first, ""); diff --git a/tools/jvmti-agents/field-counts/fieldcount.cc b/tools/jvmti-agents/field-counts/fieldcount.cc index c31a973712..5a4b00e7a5 100644 --- a/tools/jvmti-agents/field-counts/fieldcount.cc +++ b/tools/jvmti-agents/field-counts/fieldcount.cc @@ -182,7 +182,7 @@ static void DataDumpRequestCb(jvmtiEnv* jvmti) { << "\t" << "<ALL_TYPES>" << "\t" << obj_len << "\t" << total_size; - for (auto sz : class_sizes) { + for (const std::pair<std::string, size_t> sz : class_sizes) { size_t count = class_counts[sz.first]; LOG(INFO) << "\t" << field_class_name << "." << field_name << ":" << field_sig << "\t" << sz.first diff --git a/tools/jvmti-agents/simple-force-redefine/forceredefine.cc b/tools/jvmti-agents/simple-force-redefine/forceredefine.cc index 055fb8aee8..34742388cb 100644 --- a/tools/jvmti-agents/simple-force-redefine/forceredefine.cc +++ b/tools/jvmti-agents/simple-force-redefine/forceredefine.cc @@ -94,7 +94,7 @@ class JvmtiAllocator : public dex::Writer::Allocator { jvmtiEnv* jvmti_; }; -static void Transform(std::shared_ptr<ir::DexFile> ir) { +static void Transform(const std::shared_ptr<ir::DexFile>& ir) { std::unique_ptr<ir::Builder> builder; for (auto& method : ir->encoded_methods) { // Do not look into abstract/bridge/native/synthetic methods. diff --git a/tools/jvmti-agents/simple-profile/simple_profile.cc b/tools/jvmti-agents/simple-profile/simple_profile.cc index 5ead97edd8..7161142839 100644 --- a/tools/jvmti-agents/simple-profile/simple_profile.cc +++ b/tools/jvmti-agents/simple-profile/simple_profile.cc @@ -26,6 +26,7 @@ #include <sstream> #include <string> #include <unordered_map> +#include <utility> #include <vector> #include "android-base/unique_fd.h" @@ -55,7 +56,7 @@ class SimpleProfileData { SimpleProfileData( jvmtiEnv* env, std::string out_fd_name, int fd, bool dump_on_shutdown, bool dump_on_main_stop) : dump_id_(0), - out_fd_name_(out_fd_name), + out_fd_name_(std::move(out_fd_name)), out_fd_(fd), shutdown_(false), dump_on_shutdown_(dump_on_shutdown || dump_on_main_stop), @@ -79,7 +80,7 @@ class SimpleProfileData { void Shutdown(jvmtiEnv* jvmti, JNIEnv* jni); private: - void DoDump(jvmtiEnv* jvmti, JNIEnv* jni, std::unordered_map<jmethodID, uint64_t> copy); + void DoDump(jvmtiEnv* jvmti, JNIEnv* jni, const std::unordered_map<jmethodID, uint64_t>& copy); jlong dump_id_; jrawMonitorID mon_; @@ -320,7 +321,7 @@ std::ostream& operator<<(std::ostream& os, ScopedMethodInfo const& method) { void SimpleProfileData::DoDump(jvmtiEnv* jvmti, JNIEnv* jni, - std::unordered_map<jmethodID, uint64_t> copy) { + const std::unordered_map<jmethodID, uint64_t>& copy) { std::ostringstream oss; oss << "["; bool is_first = true; diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt index 6e6ccb8921..fc28acd22b 100644 --- a/tools/libcore_failures.txt +++ b/tools/libcore_failures.txt @@ -330,5 +330,27 @@ bug: 228441328, names: ["tck.java.time", "test.java.time"] +}, +{ + description: "Timing out after ojluni tests were enabled", + result: ERROR, + bug: 231439593, + names: ["org.apache.harmony.tests.java.math.BigIntegerConstructorsTest#testConstructorPrime"] +}, +{ + description: "libcore.android.system.OsConstantsTest CAP constants tests work on device only", + result: EXEC_FAILED, + modes: [host], + names: ["libcore.android.system.OsConstantsTest#test_CAP_TO_INDEX", + "libcore.android.system.OsConstantsTest#test_CAP_TO_MASK", + "libcore.android.system.OsConstantsTest#test_CAP_constants"] +}, +{ + description: "Record test doens't work properly on vogar/", + result: EXEC_FAILED, + bug: 272698028, + names: ["libcore.java.lang.RecordTest", + "crossvmtest.java.lang.RecordComponentTest", + "crossvmtest.java.lang.RecordTest"] } ] diff --git a/tools/libcore_fugu_failures.txt b/tools/libcore_fugu_failures.txt index 0fff814f5e..60b43d0571 100644 --- a/tools/libcore_fugu_failures.txt +++ b/tools/libcore_fugu_failures.txt @@ -25,6 +25,8 @@ names: [ "libcore.java.math.BigIntegerTest#test_Constructor_IILjava_util_Random", "libcore.java.math.BigIntegerTest#test_probablePrime", + "libcore.java.util.UUIDTest#testJava11Implementation_invalidInputs", + "libcore.java.util.UUIDTest#testJava8Implementation_allowsLongInputs", "libcore.javax.crypto.CipherInputStreamTest#testDecryptCorruptGCM", "libcore.javax.crypto.CipherOutputStreamTest#testDecryptCorruptGCM", "libcore.libcore.timezone.TelephonyLookupTest#createInstanceWithFallback", @@ -112,7 +114,6 @@ "org.apache.harmony.crypto.tests.javax.crypto.func.CipherRSATest#test_RSANoPadding", "org.apache.harmony.crypto.tests.javax.crypto.func.CipherRSATest#test_RSAShortKey", "org.apache.harmony.crypto.tests.javax.crypto.func.KeyGeneratorFunctionalTest#test_", - "org.apache.harmony.tests.java.math.BigIntegerConstructorsTest#testConstructorPrime", "org.apache.harmony.tests.java.math.BigIntegerTest#test_isProbablePrimeI", "org.apache.harmony.tests.java.math.OldBigIntegerTest#test_ConstructorIILjava_util_Random", "org.apache.harmony.tests.java.math.OldBigIntegerTest#test_isProbablePrimeI", @@ -127,5 +128,109 @@ "org.apache.harmony.tests.javax.security.OldSHA1PRNGSecureRandomTest#testNextBytesbyteArray03", "org.apache.harmony.tests.javax.security.OldSHA1PRNGSecureRandomTest#testSetSeedbyteArray02" ] +}, +{ + description: "Test using the getrandom() syscall, only available from Linux 3.17.", + result: ERROR, + bug: 141230711, + modes: [device], + names: [ + "test.java.awt", + "test.java.io.ByteArrayInputStream", + "test.java.io.ByteArrayOutputStream", + "test.java.io.FileReader", + "test.java.io.FileWriter", + "test.java.io.InputStream", + "test.java.io.OutputStream", + "test.java.io.PrintStream", + "test.java.io.PrintWriter", + "test.java.io.Reader", + "test.java.io.Writer", + "test.java.lang.Boolean", + "test.java.lang.ClassLoader", + "test.java.lang.Double", + "test.java.lang.Float", + "test.java.lang.Integer", + "test.java.lang.Long", + "test.java.lang.StackWalker#main", + "test.java.lang.StrictMath.CubeRootTests", + "test.java.lang.StrictMath.ExactArithTests", + "test.java.lang.StrictMath.Expm1Tests", + "test.java.lang.StrictMath.ExpTests", + "test.java.lang.StrictMath.HyperbolicTests", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard1", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard2", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard3", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard4", + "test.java.lang.StrictMath.HypotTests#testHypot", + "test.java.lang.StrictMath.Log1pTests", + "test.java.lang.StrictMath.Log10Tests", + "test.java.lang.StrictMath.MultiplicationTests", + "test.java.lang.StrictMath.PowTests", + "test.java.lang.String", + "test.java.lang.Thread", + "test.java.lang.invoke", + "test.java.lang.ref.SoftReference", + "test.java.lang.ref.BasicTest", + "test.java.lang.ref.EnqueueNullRefTest", + "test.java.lang.ref.EnqueuePollRaceTest", + "test.java.lang.ref.ReferenceCloneTest", + "test.java.lang.ref.ReferenceEnqueuePendingTest", + "test.java.math.BigDecimal", + "test.java.math.BigInteger#testArithmetic", + "test.java.math.BigInteger#testBitCount", + "test.java.math.BigInteger#testBitLength", + "test.java.math.BigInteger#testbitOps", + "test.java.math.BigInteger#testBitwise", + "test.java.math.BigInteger#testByteArrayConv", + "test.java.math.BigInteger#testConstructor", + "test.java.math.BigInteger#testDivideAndReminder", + "test.java.math.BigInteger#testDivideLarge", + "test.java.math.BigInteger#testModExp", + "test.java.math.BigInteger#testMultiplyLarge", + "test.java.math.BigInteger#testNextProbablePrime", + "test.java.math.BigInteger#testPow", + "test.java.math.BigInteger#testSerialize", + "test.java.math.BigInteger#testShift", + "test.java.math.BigInteger#testSquare", + "test.java.math.BigInteger#testSquareLarge", + "test.java.math.BigInteger#testSquareRootAndReminder", + "test.java.math.BigInteger#testStringConv_generic", + "test.java.math.RoundingMode", + "test.java.net.DatagramSocket", + "test.java.net.Socket", + "test.java.net.SocketOptions", + "test.java.net.URLDecoder", + "test.java.net.URLEncoder", + "test.java.nio.channels.Channels", + "test.java.nio.channels.SelectionKey", + "test.java.nio.channels.Selector", + "test.java.nio.file", + "test.java.security.cert", + "test.java.security.KeyAgreement.KeyAgreementTest", + "test.java.security.KeyAgreement.KeySizeTest#testECDHKeySize", + "test.java.security.KeyAgreement.KeySpecTest", + "test.java.security.KeyAgreement.MultiThreadTest", + "test.java.security.KeyAgreement.NegativeTest", + "test.java.security.KeyStore", + "test.java.security.Provider", + "test.java.util.Arrays", + "test.java.util.Collection", + "test.java.util.Collections", + "test.java.util.Date", + "test.java.util.EnumMap", + "test.java.util.EnumSet", + "test.java.util.GregorianCalendar", + "test.java.util.LinkedHashMap", + "test.java.util.LinkedHashSet", + "test.java.util.List", + "test.java.util.Map", + "test.java.util.Optional", + "test.java.util.TimeZone", + "test.java.util.concurrent", + "test.java.util.function", + "test.java.util.stream", + "test.java.util.zip.ZipFile" + ] } ] diff --git a/tools/libcore_gcstress_debug_failures.txt b/tools/libcore_gcstress_debug_failures.txt index 21931893b5..c9316106c1 100644 --- a/tools/libcore_gcstress_debug_failures.txt +++ b/tools/libcore_gcstress_debug_failures.txt @@ -50,7 +50,6 @@ "org.apache.harmony.luni.tests.internal.net.www.protocol.https.HttpsURLConnectionTest#testConsequentProxyConnection", "org.apache.harmony.tests.java.lang.ref.ReferenceQueueTest#test_removeJ", "org.apache.harmony.tests.java.lang.ProcessManagerTest#testSleep", - "org.apache.harmony.tests.java.math.BigIntegerConstructorsTest#testConstructorPrime", "org.apache.harmony.tests.java.util.TimerTest#testOverdueTaskExecutesImmediately", "org.apache.harmony.tests.java.util.WeakHashMapTest#test_keySet_hasNext" ] @@ -71,5 +70,11 @@ names: ["jsr166.CompletableFutureTest#testCompleteOnTimeout_completed", "jsr166.CompletableFutureTest#testDelayedExecutor" ] +}, +{ + description: "SocketTimeout test gcstress and debug.", + result: EXEC_FAILED, + bug: 259530489, + names: ["org.apache.harmony.luni.tests.java.net.URLConnectionTest#test_setReadTimeoutI_SocketTimeoutException"] } ] diff --git a/tools/libcore_gcstress_failures.txt b/tools/libcore_gcstress_failures.txt index 55bba72005..81d6ca09da 100644 --- a/tools/libcore_gcstress_failures.txt +++ b/tools/libcore_gcstress_failures.txt @@ -36,7 +36,6 @@ "libcore.java.util.stream.CollectorsTest#counting_largeStream", "org.apache.harmony.tests.java.lang.ref.ReferenceQueueTest#test_remove", "org.apache.harmony.tests.java.lang.String2Test#test_getBytes", - "org.apache.harmony.tests.java.math.BigIntegerConstructorsTest#testConstructorPrime", "org.apache.harmony.tests.java.text.DateFormatTest#test_getAvailableLocales", "org.apache.harmony.tests.java.util.TimerTest#testOverdueTaskExecutesImmediately", "org.apache.harmony.tests.java.util.WeakHashMapTest#test_keySet_hasNext"] diff --git a/tools/luci/config/generated/cr-buildbucket.cfg b/tools/luci/config/generated/cr-buildbucket.cfg index e4a5923986..1da398c550 100644 --- a/tools/luci/config/generated/cr-buildbucket.cfg +++ b/tools/luci/config/generated/cr-buildbucket.cfg @@ -17,7 +17,8 @@ buckets { builders { name: "angler-armv7-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:angler-armv7-debug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -35,13 +36,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "angler-armv7-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:angler-armv7-ndebug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -59,13 +61,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "angler-armv7-non-gen-cc" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:angler-armv7-non-gen-cc" + dimensions: "device_type:oriole" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -83,13 +86,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "angler-armv8-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:angler-armv8-debug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -107,13 +111,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "angler-armv8-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:angler-armv8-ndebug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -131,13 +136,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "angler-armv8-non-gen-cc" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:angler-armv8-non-gen-cc" + dimensions: "device_type:oriole" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -155,13 +161,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "bullhead-armv7-gcstress-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:bullhead-armv7-gcstress-ndebug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -179,13 +186,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "bullhead-armv8-gcstress-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:bullhead-armv8-gcstress-debug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -203,13 +211,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "bullhead-armv8-gcstress-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:bullhead-armv8-gcstress-ndebug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -227,13 +236,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "fugu-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:fugu-debug" + dimensions: "device_type:fugu" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -251,13 +261,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "fugu-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:fugu-ndebug" + dimensions: "device_type:fugu" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -275,13 +286,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86-cms" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86-cms" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -299,13 +310,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86-debug" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -323,13 +334,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86-gcstress-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86-gcstress-debug" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -347,13 +358,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86-ndebug" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -371,13 +382,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86-poison-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86-poison-debug" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -395,13 +406,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86_64-cdex-fast" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86_64-cdex-fast" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -419,13 +430,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86_64-cms" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86_64-cms" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -443,13 +454,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86_64-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86_64-debug" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -467,13 +478,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86_64-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86_64-ndebug" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -491,13 +502,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86_64-non-gen-cc" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86_64-non-gen-cc" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -515,13 +526,13 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "host-x86_64-poison-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:host-x86_64-poison-debug" + dimensions: "os:Linux" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -539,13 +550,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "walleye-armv7-poison-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:walleye-armv7-poison-debug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -563,13 +575,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "walleye-armv8-poison-debug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:walleye-armv8-poison-debug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -587,13 +600,14 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } builders { name: "walleye-armv8-poison-ndebug" swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:walleye-armv8-poison-ndebug" + dimensions: "device_type:bonito|oriole|walleye" + dimensions: "os:Android" dimensions: "pool:luci.art.ci" recipe { name: "art" @@ -611,7 +625,7 @@ buckets { service_account: "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { key: "luci.recipes.use_python3" - value: 10 + value: 100 } } } diff --git a/tools/luci/config/generated/luci-scheduler.cfg b/tools/luci/config/generated/luci-scheduler.cfg index d6c6ab58ab..ba7bceeae5 100644 --- a/tools/luci/config/generated/luci-scheduler.cfg +++ b/tools/luci/config/generated/luci-scheduler.cfg @@ -356,6 +356,40 @@ trigger { refs: "regexp:refs/heads/master-art" } } +trigger { + id: "vogar" + realm: "ci" + acl_sets: "ci" + triggers: "angler-armv7-debug" + triggers: "angler-armv7-ndebug" + triggers: "angler-armv7-non-gen-cc" + triggers: "angler-armv8-debug" + triggers: "angler-armv8-ndebug" + triggers: "angler-armv8-non-gen-cc" + triggers: "bullhead-armv7-gcstress-ndebug" + triggers: "bullhead-armv8-gcstress-debug" + triggers: "bullhead-armv8-gcstress-ndebug" + triggers: "fugu-debug" + triggers: "fugu-ndebug" + triggers: "host-x86-cms" + triggers: "host-x86-debug" + triggers: "host-x86-gcstress-debug" + triggers: "host-x86-ndebug" + triggers: "host-x86-poison-debug" + triggers: "host-x86_64-cdex-fast" + triggers: "host-x86_64-cms" + triggers: "host-x86_64-debug" + triggers: "host-x86_64-ndebug" + triggers: "host-x86_64-non-gen-cc" + triggers: "host-x86_64-poison-debug" + triggers: "walleye-armv7-poison-debug" + triggers: "walleye-armv8-poison-debug" + triggers: "walleye-armv8-poison-ndebug" + gitiles { + repo: "https://android.googlesource.com/platform/external/vogar" + refs: "regexp:refs/heads/master" + } +} acl_sets { name: "ci" acls { diff --git a/tools/luci/config/generated/project.cfg b/tools/luci/config/generated/project.cfg index 4844ab4987..f9f78772a8 100644 --- a/tools/luci/config/generated/project.cfg +++ b/tools/luci/config/generated/project.cfg @@ -7,7 +7,7 @@ name: "art" access: "group:all" lucicfg { - version: "1.30.11" + version: "1.33.7" package_dir: ".." config_dir: "generated" entry_point: "main.star" diff --git a/tools/luci/config/main.star b/tools/luci/config/main.star index f4ad488020..b1ecde1ec9 100755 --- a/tools/luci/config/main.star +++ b/tools/luci/config/main.star @@ -23,7 +23,7 @@ After modifying this file execute it ('./main.star') to regenerate the configs. lucicfg.check_version("1.30.9", "Please update depot_tools") luci.builder.defaults.experiments.set({ - "luci.recipes.use_python3": 10, + "luci.recipes.use_python3": 100, }) # Use LUCI Scheduler BBv2 names and add Scheduler realms configs. @@ -141,13 +141,20 @@ luci.gitiles_poller( ) luci.gitiles_poller( + name = "vogar", + bucket = "ci", + repo = "https://android.googlesource.com/platform/external/vogar", + refs = ["refs/heads/master"], +) + +luci.gitiles_poller( name = "manifest", bucket = "ci", repo = "https://android.googlesource.com/platform/manifest", refs = ["refs/heads/master-art"], ) -def ci_builder(name, category, short_name): +def ci_builder(name, category, short_name, dimensions): luci.builder( name = name, bucket = "ci", @@ -156,11 +163,8 @@ def ci_builder(name, category, short_name): cipd_version = "refs/heads/main", name = "art", ), - dimensions = { + dimensions = dimensions | { "pool": "luci.art.ci", - - # Some builders require specific hardware, so we make the assignment in bots.cfg - "builder": name, }, service_account = "art-ci-builder@chops-service-accounts.iam.gserviceaccount.com", @@ -185,6 +189,7 @@ def ci_builder(name, category, short_name): "art", "libcore", "manifest", + "vogar", ], ) luci.console_view_entry( @@ -194,28 +199,37 @@ def ci_builder(name, category, short_name): short_name = short_name, ) -ci_builder("angler-armv7-debug", "angler|armv7", "dbg") -ci_builder("angler-armv7-non-gen-cc", "angler|armv7", "ngen") -ci_builder("angler-armv7-ndebug", "angler|armv7", "ndbg") -ci_builder("angler-armv8-debug", "angler|armv8", "dbg") -ci_builder("angler-armv8-non-gen-cc", "angler|armv8", "ngen") -ci_builder("angler-armv8-ndebug", "angler|armv8", "ndbg") -ci_builder("bullhead-armv7-gcstress-ndebug", "bullhead|armv7|gcstress", "dbg") -ci_builder("bullhead-armv8-gcstress-debug", "bullhead|armv8|gcstress", "dbg") -ci_builder("bullhead-armv8-gcstress-ndebug", "bullhead|armv8|gcstress", "ndbg") -ci_builder("fugu-debug", "fugu", "dbg") -ci_builder("fugu-ndebug", "fugu", "ndbg") -ci_builder("host-x86-cms", "host|x86", "cms") -ci_builder("host-x86-debug", "host|x86", "dbg") -ci_builder("host-x86-ndebug", "host|x86", "ndbg") -ci_builder("host-x86-gcstress-debug", "host|x86", "gcs") -ci_builder("host-x86-poison-debug", "host|x86", "psn") -ci_builder("host-x86_64-cdex-fast", "host|x64", "cdx") -ci_builder("host-x86_64-cms", "host|x64", "cms") -ci_builder("host-x86_64-debug", "host|x64", "dbg") -ci_builder("host-x86_64-non-gen-cc", "host|x64", "ngen") -ci_builder("host-x86_64-ndebug", "host|x64", "ndbg") -ci_builder("host-x86_64-poison-debug", "host|x64", "psn") -ci_builder("walleye-armv7-poison-debug", "walleye|armv7|poison", "dbg") -ci_builder("walleye-armv8-poison-debug", "walleye|armv8|poison", "dbg") -ci_builder("walleye-armv8-poison-ndebug", "walleye|armv8|poison", "ndbg") +# Dimensions specify which bots we can run on. +host_dims = {"os": "Linux"} +target_dims = {"os": "Android"} +arm_target_dims = target_dims | {"device_type": "bonito|oriole|walleye"} +x86_target_dims = target_dims | {"device_type": "fugu"} + +# userfault-GC configurations must be run on Pixel 6. +userfault_gc_target_dims = target_dims | {"device_type": "oriole"} + +ci_builder("angler-armv7-debug", "angler|armv7", "dbg", arm_target_dims) +ci_builder("angler-armv7-non-gen-cc", "angler|armv7", "ngen", userfault_gc_target_dims) +ci_builder("angler-armv7-ndebug", "angler|armv7", "ndbg", arm_target_dims) +ci_builder("angler-armv8-debug", "angler|armv8", "dbg", arm_target_dims) +ci_builder("angler-armv8-non-gen-cc", "angler|armv8", "ngen", userfault_gc_target_dims) +ci_builder("angler-armv8-ndebug", "angler|armv8", "ndbg", arm_target_dims) +ci_builder("bullhead-armv7-gcstress-ndebug", "bullhead|armv7|gcstress", "dbg", arm_target_dims) +ci_builder("bullhead-armv8-gcstress-debug", "bullhead|armv8|gcstress", "dbg", arm_target_dims) +ci_builder("bullhead-armv8-gcstress-ndebug", "bullhead|armv8|gcstress", "ndbg", arm_target_dims) +ci_builder("fugu-debug", "fugu", "dbg", x86_target_dims) +ci_builder("fugu-ndebug", "fugu", "ndbg", x86_target_dims) +ci_builder("host-x86-cms", "host|x86", "cms", host_dims) +ci_builder("host-x86-debug", "host|x86", "dbg", host_dims) +ci_builder("host-x86-ndebug", "host|x86", "ndbg", host_dims) +ci_builder("host-x86-gcstress-debug", "host|x86", "gcs", host_dims) +ci_builder("host-x86-poison-debug", "host|x86", "psn", host_dims) +ci_builder("host-x86_64-cdex-fast", "host|x64", "cdx", host_dims) +ci_builder("host-x86_64-cms", "host|x64", "cms", host_dims) +ci_builder("host-x86_64-debug", "host|x64", "dbg", host_dims) +ci_builder("host-x86_64-non-gen-cc", "host|x64", "ngen", host_dims) +ci_builder("host-x86_64-ndebug", "host|x64", "ndbg", host_dims) +ci_builder("host-x86_64-poison-debug", "host|x64", "psn", host_dims) +ci_builder("walleye-armv7-poison-debug", "walleye|armv7|poison", "dbg", arm_target_dims) +ci_builder("walleye-armv8-poison-debug", "walleye|armv8|poison", "dbg", arm_target_dims) +ci_builder("walleye-armv8-poison-ndebug", "walleye|armv8|poison", "ndbg", arm_target_dims) diff --git a/tools/prebuilt_libjdwp_art_failures.txt b/tools/prebuilt_libjdwp_art_failures.txt index ee59315ccb..4ded7d56ed 100644 --- a/tools/prebuilt_libjdwp_art_failures.txt +++ b/tools/prebuilt_libjdwp_art_failures.txt @@ -106,5 +106,5 @@ result: EXEC_FAILED, bug: 69169846, name: "org.apache.harmony.jpda.tests.jdwp.DDM_DDMTest#testChunk001" -}, +} ] diff --git a/tools/public.libraries.buildbot.txt b/tools/public.libraries.buildbot.txt index e23cf2cfb4..9b0dc6858a 100644 --- a/tools/public.libraries.buildbot.txt +++ b/tools/public.libraries.buildbot.txt @@ -1,6 +1,6 @@ -libbacktrace.so libc.so libc++.so libdl.so libm.so libnativehelper.so +libunwindstack.so diff --git a/tools/run-gtests.sh b/tools/run-gtests.sh index 21064c1739..da61c7e3cc 100755 --- a/tools/run-gtests.sh +++ b/tools/run-gtests.sh @@ -59,20 +59,47 @@ done options="$@" +run_in_chroot() { + if [ -n "$ART_TEST_ON_VM" ]; then + $ART_SSH_CMD $ART_CHROOT_CMD $@ + else + "$adb" shell chroot "$ART_TEST_CHROOT" $@ + fi +} + if [[ ${#tests[@]} -eq 0 ]]; then # Search for executables under the `bin/art` directory of the ART APEX. - readarray -t tests <<<$("$adb" shell chroot "$ART_TEST_CHROOT" \ + readarray -t tests <<<$(run_in_chroot \ find "$android_art_root/bin/art" -type f -perm /ugo+x | sort) fi +maybe_get_fake_dex2oatbootclasspath() { + if [ -n "$ART_TEST_ON_VM" ]; then + return + fi + dex2oatbootclasspath=$("$adb" shell echo \$DEX2OATBOOTCLASSPATH) + if [ -n "$dex2oatbootclasspath" ]; then + # The device has a real DEX2OATBOOTCLASSPATH. + # This is the usual case. + return + fi + bootclasspath=$("$adb" shell echo \$BOOTCLASSPATH) + # Construct a fake DEX2OATBOOTCLASSPATH from the elements in BOOTCLASSPATH except the last one. + # BOOTCLASSPATH cannot be used by the runtime in chroot anyway, so it doesn't hurt to construct a + # fake DEX2OATBOOTCLASSPATH just to make the runtime happy. + # This is only needed on old Android platforms such as Android P. + echo "DEX2OATBOOTCLASSPATH=${bootclasspath%:*}" +} + failing_tests=() for t in ${tests[@]}; do echo "$t" - "$adb" shell chroot "$ART_TEST_CHROOT" \ + run_in_chroot \ env ANDROID_ART_ROOT="$android_art_root" \ ANDROID_I18N_ROOT="$android_i18n_root" \ ANDROID_TZDATA_ROOT="$android_tzdata_root" \ + $(maybe_get_fake_dex2oatbootclasspath) \ $t $options \ || failing_tests+=("$t") done diff --git a/tools/run-libcore-tests.py b/tools/run-libcore-tests.py index 1e6070a51e..c6958f1b6c 100755 --- a/tools/run-libcore-tests.py +++ b/tools/run-libcore-tests.py @@ -42,6 +42,7 @@ def parse_args(): help='Enable GC stress configuration (device|host only).') parser.add_argument('tests', nargs="*", help='Name(s) of the test(s) to run') + parser.add_argument('--verbose', action='store_true', help='Print verbose output from vogar.') return parser.parse_args() ART_TEST_ANDROID_ROOT = os.environ.get("ART_TEST_ANDROID_ROOT", "/system") @@ -91,7 +92,10 @@ LIBCORE_TEST_NAMES = [ "libcore.sun.util", "libcore.xml", "org.apache.harmony.annotation", - "org.apache.harmony.luni", + "org.apache.harmony.luni.tests.internal.net.www.protocol.http.HttpURLConnection", + "org.apache.harmony.luni.tests.internal.net.www.protocol.https.HttpsURLConnection", + "org.apache.harmony.luni.tests.java.io", + "org.apache.harmony.luni.tests.java.net", "org.apache.harmony.nio", "org.apache.harmony.regex", "org.apache.harmony.testframework", @@ -122,7 +126,8 @@ LIBCORE_TEST_NAMES = [ "test.java.lang.Long", # Sharded test.java.lang.StrictMath "test.java.lang.StrictMath.CubeRootTests", - "test.java.lang.StrictMath.ExactArithTests", + # TODO: disable the test until b/248208762 is fixed. + # "test.java.lang.StrictMath.ExactArithTests", "test.java.lang.StrictMath.Expm1Tests", "test.java.lang.StrictMath.ExpTests", "test.java.lang.StrictMath.HyperbolicTests", @@ -159,21 +164,15 @@ LIBCORE_TEST_NAMES = [ "test.java.math.BigInteger#testDivideAndReminder", "test.java.math.BigInteger#testDivideLarge", "test.java.math.BigInteger#testModExp", - "test.java.math.BigInteger#testModInv", "test.java.math.BigInteger#testMultiplyLarge", "test.java.math.BigInteger#testNextProbablePrime", "test.java.math.BigInteger#testPow", - "test.java.math.BigInteger#testPrime", "test.java.math.BigInteger#testSerialize", "test.java.math.BigInteger#testShift", "test.java.math.BigInteger#testSquare", "test.java.math.BigInteger#testSquareLarge", - "test.java.math.BigInteger#testSquareRoot", "test.java.math.BigInteger#testSquareRootAndReminder", "test.java.math.BigInteger#testStringConv_generic", - "test.java.math.BigInteger#testStringConv_schoenhage_threshold_pow0", - "test.java.math.BigInteger#testStringConv_schoenhage_threshold_pow1", - "test.java.math.BigInteger#testStringConv_schoenhage_threshold_pow2", "test.java.math.RoundingMode", # test.java.net "test.java.net.DatagramSocket", @@ -190,7 +189,6 @@ LIBCORE_TEST_NAMES = [ "test.java.security.cert", # Sharded test.java.security.KeyAgreement "test.java.security.KeyAgreement.KeyAgreementTest", - "test.java.security.KeyAgreement.KeySizeTest#testDHKeySize", "test.java.security.KeyAgreement.KeySizeTest#testECDHKeySize", "test.java.security.KeyAgreement.KeySpecTest", "test.java.security.KeyAgreement.MultiThreadTest", @@ -242,6 +240,130 @@ BOOT_CLASSPATH = [ CLASSPATH = ["core-tests", "core-ojtests", "jsr166-tests", "mockito-target"] +SLOW_OJLUNI_TESTS = { + "test.java.awt", + "test.java.lang.String", + "test.java.lang.invoke", + "test.java.nio.channels.Selector", + "test.java.time", + "test.java.util.Arrays", + "test.java.util.Map", + "test.java.util.concurrent", + "test.java.util.stream", + "test.java.util.zip.ZipFile", + "tck.java.time", +} + +# Disabled to unblock art-buildbot +# These tests fail with "java.io.IOException: Stream closed", tracked in +# http://b/235566533 and http://b/208639267 +DISABLED_GCSTRESS_DEBUG_TESTS = { + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard1", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard2", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard3", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard4", + "test.java.math.BigDecimal", + "test.java.math.BigInteger#testConstructor", +} + +DISABLED_FUGU_TESTS = { + "org.apache.harmony.luni.tests.internal.net.www.protocol.http.HttpURLConnection", + "org.apache.harmony.luni.tests.internal.net.www.protocol.https.HttpsURLConnection", + "test.java.awt", + "test.java.io.ByteArrayInputStream", + "test.java.io.ByteArrayOutputStream", + "test.java.io.InputStream", + "test.java.io.OutputStream", + "test.java.io.PrintStream", + "test.java.io.PrintWriter", + "test.java.io.Reader", + "test.java.io.Writer", + "test.java.lang.Boolean", + "test.java.lang.ClassLoader", + "test.java.lang.Double", + "test.java.lang.Float", + "test.java.lang.Integer", + "test.java.lang.Long", + "test.java.lang.StrictMath.CubeRootTests", + "test.java.lang.StrictMath.Expm1Tests", + "test.java.lang.StrictMath.ExpTests", + "test.java.lang.StrictMath.HyperbolicTests", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard1", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard2", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard3", + "test.java.lang.StrictMath.HypotTests#testAgainstTranslit_shard4", + "test.java.lang.StrictMath.HypotTests#testHypot", + "test.java.lang.StrictMath.Log1pTests", + "test.java.lang.StrictMath.Log10Tests", + "test.java.lang.StrictMath.MultiplicationTests", + "test.java.lang.StrictMath.PowTests", + "test.java.lang.String", + "test.java.lang.Thread", + "test.java.lang.invoke", + "test.java.lang.ref.SoftReference", + "test.java.lang.ref.BasicTest", + "test.java.lang.ref.EnqueueNullRefTest", + "test.java.lang.ref.EnqueuePollRaceTest", + "test.java.lang.ref.ReferenceCloneTest", + "test.java.lang.ref.ReferenceEnqueuePendingTest", + "test.java.math.BigDecimal", + "test.java.math.BigInteger#testArithmetic", + "test.java.math.BigInteger#testBitCount", + "test.java.math.BigInteger#testBitLength", + "test.java.math.BigInteger#testbitOps", + "test.java.math.BigInteger#testBitwise", + "test.java.math.BigInteger#testByteArrayConv", + "test.java.math.BigInteger#testConstructor", + "test.java.math.BigInteger#testDivideAndReminder", + "test.java.math.BigInteger#testDivideLarge", + "test.java.math.BigInteger#testModExp", + "test.java.math.BigInteger#testMultiplyLarge", + "test.java.math.BigInteger#testNextProbablePrime", + "test.java.math.BigInteger#testPow", + "test.java.math.BigInteger#testSerialize", + "test.java.math.BigInteger#testShift", + "test.java.math.BigInteger#testSquare", + "test.java.math.BigInteger#testSquareLarge", + "test.java.math.BigInteger#testSquareRootAndReminder", + "test.java.math.BigInteger#testStringConv_generic", + "test.java.math.RoundingMode", + "test.java.net.DatagramSocket", + "test.java.net.Socket", + "test.java.net.SocketOptions", + "test.java.net.URLDecoder", + "test.java.net.URLEncoder", + "test.java.nio.channels.Channels", + "test.java.nio.channels.SelectionKey", + "test.java.nio.channels.Selector", + "test.java.nio.file", + "test.java.security.cert", + "test.java.security.KeyAgreement.KeyAgreementTest", + "test.java.security.KeyAgreement.KeySizeTest#testECDHKeySize", + "test.java.security.KeyAgreement.KeySpecTest", + "test.java.security.KeyAgreement.MultiThreadTest", + "test.java.security.KeyAgreement.NegativeTest", + "test.java.security.KeyStore", + "test.java.security.Provider", + "test.java.time", + "test.java.util.Arrays", + "test.java.util.Collection", + "test.java.util.Collections", + "test.java.util.Date", + "test.java.util.EnumMap", + "test.java.util.EnumSet", + "test.java.util.GregorianCalendar", + "test.java.util.LinkedHashMap", + "test.java.util.LinkedHashSet", + "test.java.util.List", + "test.java.util.Map", + "test.java.util.Optional", + "test.java.util.TestFormatter", + "test.java.util.TimeZone", + "test.java.util.function", + "test.java.util.stream", + "tck.java.time", +} + def get_jar_filename(classpath): base_path = (ANDROID_PRODUCT_OUT + "/../..") if ANDROID_PRODUCT_OUT else "out/target" base_path = os.path.normpath(base_path) # Normalize ".." components for readability. @@ -275,6 +397,13 @@ def get_test_names(): # See b/78228743 and b/178351808. if args.gcstress or args.debug or args.mode == "jvm": test_names = list(t for t in test_names if not t.startswith("libcore.highmemorytest")) + test_names = list(filter(lambda x: x not in SLOW_OJLUNI_TESTS, test_names)) + if args.gcstress and args.debug: + test_names = list(filter(lambda x: x not in DISABLED_GCSTRESS_DEBUG_TESTS, test_names)) + if not args.getrandom: + # Disable libcore.highmemorytest due to limited ram on fugu. http://b/258173036 + test_names = list(filter(lambda x: x not in DISABLED_FUGU_TESTS and + not x.startswith("libcore.highmemorytest"), test_names)) return test_names def get_vogar_command(test_name): @@ -282,6 +411,7 @@ def get_vogar_command(test_name): if args.mode == "device": cmd.append("--mode=device --vm-arg -Ximage:/system/framework/art_boot_images/boot.art") cmd.append("--vm-arg -Xbootclasspath:" + ":".join(BOOT_CLASSPATH)) + if args.mode == "host": # We explicitly give a wrong path for the image, to ensure vogar # will create a boot image with the default compiler. Note that @@ -298,11 +428,16 @@ def get_vogar_command(test_name): if args.debug: cmd.append("--vm-arg -XXlib:libartd.so --vm-arg -XX:SlowDebug=true") + # The only device in go/art-buildbot without getrandom is fugu. We limit the amount of memory + # per runtime for fugu to avoid low memory killer, fugu has 4-cores 1GB RAM (b/258171768). + if not args.getrandom: + cmd.append("--vm-arg -Xmx128M") + if args.mode == "device": if ART_TEST_CHROOT: cmd.append(f"--chroot {ART_TEST_CHROOT} --device-dir=/tmp/vogar/test-{test_name}") else: - cmd.append("--device-dir=/data/local/tmp/vogar/test-{test_name}") + cmd.append(f"--device-dir=/data/local/tmp/vogar/test-{test_name}") cmd.append(f"--vm-command={ART_TEST_ANDROID_ROOT}/bin/art") else: cmd.append(f"--device-dir=/tmp/vogar/test-{test_name}") @@ -314,6 +449,9 @@ def get_vogar_command(test_name): cmd.append("--vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken") cmd.append("--vm-arg -Xusejit:{}".format(str(args.jit).lower())) + if args.verbose: + cmd.append("--verbose") + # Suppress color codes if not attached to a terminal if not sys.stdout.isatty(): cmd.append("--no-color") @@ -370,7 +508,7 @@ def main(): print(f"Running {len(futures)} tasks on {args.jobs} core(s)...\n") for i, future in enumerate(concurrent.futures.as_completed(futures)): test_name, cmd, stdout, exit_code = future.result() - if exit_code != 0 or args.dry_run: + if exit_code != 0 or args.dry_run or args.verbose: print(cmd) print(stdout.strip()) else: diff --git a/tools/run-libjdwp-tests.sh b/tools/run-libjdwp-tests.sh index efb2737cad..06e34f9c3d 100755 --- a/tools/run-libjdwp-tests.sh +++ b/tools/run-libjdwp-tests.sh @@ -138,6 +138,10 @@ if [[ "$debug" = "yes" && "$has_gcstress" = "yes" ]]; then expectations="$expectations --expectations $PWD/art/tools/external_oj_libjdwp_art_gcstress_debug_failures.txt" fi +if [[ "${ART_USE_READ_BARRIER}" = "false" ]]; then + expectations="$expectations --expectations $PWD/art/tools/external_oj_libjdwp_art_no_read_barrier_failures.txt" +fi + function verbose_run() { echo "$@" env "$@" diff --git a/tools/signal_dumper/Android.bp b/tools/signal_dumper/Android.bp index 33450d1301..00948b8aad 100644 --- a/tools/signal_dumper/Android.bp +++ b/tools/signal_dumper/Android.bp @@ -48,18 +48,6 @@ cc_defaults { }, } -cc_defaults { - name: "signal_dumper_libbacktrace_static_deps", - defaults: [ - "signal_dumper_libbase_static_deps", - "signal_dumper_libunwindstack_static_deps", - ], - static_libs: [ - "libbase", - "libunwindstack", - ], -} - art_cc_binary { name: "signal_dumper", @@ -73,14 +61,14 @@ art_cc_binary { defaults: [ "art_defaults", - "signal_dumper_libbacktrace_static_deps", "signal_dumper_libbase_static_deps", + "signal_dumper_libunwindstack_static_deps", ], srcs: ["signal_dumper.cc"], static_libs: [ - "libbacktrace", "libbase", + "libunwindstack", ], } diff --git a/tools/signal_dumper/signal_dumper.cc b/tools/signal_dumper/signal_dumper.cc index e9a589e699..bedb8dc6fc 100644 --- a/tools/signal_dumper/signal_dumper.cc +++ b/tools/signal_dumper/signal_dumper.cc @@ -15,6 +15,7 @@ */ #include <dirent.h> +#include <inttypes.h> #include <poll.h> #include <sys/prctl.h> #include <sys/ptrace.h> @@ -38,8 +39,7 @@ #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> -#include <backtrace/Backtrace.h> -#include <backtrace/BacktraceMap.h> +#include <unwindstack/AndroidUnwinder.h> namespace art { namespace { @@ -368,11 +368,13 @@ std::set<pid_t> PtraceSiblings(pid_t pid) { } void DumpABI(pid_t forked_pid) { - enum class ABI { kArm, kArm64, kX86, kX86_64 }; + enum class ABI { kArm, kArm64, kRiscv64, kX86, kX86_64 }; #if defined(__arm__) constexpr ABI kDumperABI = ABI::kArm; #elif defined(__aarch64__) constexpr ABI kDumperABI = ABI::kArm64; +#elif defined(__riscv) + constexpr ABI kDumperABI = ABI::kRiscv64; #elif defined(__i386__) constexpr ABI kDumperABI = ABI::kX86; #elif defined(__x86_64__) @@ -394,6 +396,9 @@ void DumpABI(pid_t forked_pid) { case ABI::kArm64: to_print = ABI::kArm64; break; + case ABI::kRiscv64: + to_print = ABI::kRiscv64; + break; case ABI::kX86: case ABI::kX86_64: to_print = ABI::kX86_64; @@ -408,6 +413,9 @@ void DumpABI(pid_t forked_pid) { case ABI::kArm64: to_print = io_vec.iov_len == 18 * sizeof(uint32_t) ? ABI::kArm : ABI::kArm64; break; + case ABI::kRiscv64: + to_print = ABI::kRiscv64; + break; case ABI::kX86: case ABI::kX86_64: to_print = io_vec.iov_len == 17 * sizeof(uint32_t) ? ABI::kX86 : ABI::kX86_64; @@ -424,6 +432,9 @@ void DumpABI(pid_t forked_pid) { case ABI::kArm64: abi_str = "arm64"; break; + case ABI::kRiscv64: + abi_str = "riscv64"; + break; case ABI::kX86: abi_str = "x86"; break; @@ -492,11 +503,10 @@ constexpr bool kIs64Bit = true; constexpr bool kIs64Bit = false; #endif -void DumpThread(pid_t pid, +void DumpThread(unwindstack::AndroidRemoteUnwinder& unwinder, pid_t pid, pid_t tid, const std::string* addr2line_path, - const char* prefix, - BacktraceMap* map) { + const char* prefix) { LOG(ERROR) << std::endl << "=== pid: " << pid << " tid: " << tid << " ===" << std::endl; constexpr uint32_t kMaxWaitMicros = 1000 * 1000; // 1s. @@ -504,50 +514,41 @@ void DumpThread(pid_t pid, LOG(ERROR) << "Failed to wait for sigstop on " << tid; } - std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map)); - if (backtrace == nullptr) { - LOG(ERROR) << prefix << "(failed to create Backtrace for thread " << tid << ")"; - return; - } - backtrace->SetSkipFrames(false); - if (!backtrace->Unwind(0, nullptr)) { - LOG(ERROR) << prefix << "(backtrace::Unwind failed for thread " << tid - << ": " << backtrace->GetErrorString(backtrace->GetError()) << ")"; - return; - } - if (backtrace->NumFrames() == 0) { - LOG(ERROR) << prefix << "(no native stack frames for thread " << tid << ")"; + unwindstack::AndroidUnwinderData data; + if (!unwinder.Unwind(tid, data)) { + LOG(ERROR) << prefix << "(Unwind failed for thread " << tid << ": " + << data.GetErrorString() << ")"; return; } std::unique_ptr<addr2line::Addr2linePipe> addr2line_state; - - for (Backtrace::const_iterator it = backtrace->begin(); - it != backtrace->end(); ++it) { + data.DemangleFunctionNames(); + for (const unwindstack::FrameData& frame : data.frames) { std::ostringstream oss; - oss << prefix << StringPrintf("#%02zu pc ", it->num); + oss << prefix << StringPrintf("#%02zu pc ", frame.num); bool try_addr2line = false; - if (!BacktraceMap::IsValid(it->map)) { - oss << StringPrintf(kIs64Bit ? "%016" PRIx64 " ???" : "%08" PRIx64 " ???", it->pc); + if (frame.map_info == nullptr) { + oss << StringPrintf(kIs64Bit ? "%016" PRIx64 " ???" : "%08" PRIx64 " ???", frame.pc); } else { - oss << StringPrintf(kIs64Bit ? "%016" PRIx64 " " : "%08" PRIx64 " ", it->rel_pc); - if (it->map.name.empty()) { - oss << StringPrintf("<anonymous:%" PRIx64 ">", it->map.start); + oss << StringPrintf(kIs64Bit ? "%016" PRIx64 " " : "%08" PRIx64 " ", frame.rel_pc); + if (frame.map_info->name().empty()) { + oss << StringPrintf("<anonymous:%" PRIx64 ">", frame.map_info->start()); } else { - oss << it->map.name; + oss << frame.map_info->name().c_str(); } - if (it->map.offset != 0) { - oss << StringPrintf(" (offset %" PRIx64 ")", it->map.offset); + if (frame.map_info->offset() != 0) { + oss << StringPrintf(" (offset %" PRIx64 ")", frame.map_info->offset()); } oss << " ("; - if (!it->func_name.empty()) { - oss << it->func_name; - if (it->func_offset != 0) { - oss << "+" << it->func_offset; + const std::string& function_name = frame.function_name; + if (!function_name.empty()) { + oss << function_name; + if (frame.function_offset != 0) { + oss << "+" << frame.function_offset; } // Functions found using the gdb jit interface will be in an empty // map that cannot be found using addr2line. - if (!it->map.name.empty()) { + if (!frame.map_info->name().empty()) { try_addr2line = true; } } else { @@ -558,8 +559,8 @@ void DumpThread(pid_t pid, LOG(ERROR) << oss.str() << std::endl; if (try_addr2line && addr2line_path != nullptr) { addr2line::Addr2line(*addr2line_path, - it->map.name, - it->rel_pc, + frame.map_info->name(), + frame.rel_pc, LOG_STREAM(ERROR), prefix, &addr2line_state); @@ -593,14 +594,9 @@ void DumpProcess(pid_t forked_pid, const std::atomic<bool>& saw_wif_stopped_for_ LOG(ERROR) << "Did not receive SIGSTOP for pid " << forked_pid; } - std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(forked_pid)); - if (backtrace_map == nullptr) { - LOG(ERROR) << "Could not create BacktraceMap"; - return; - } - + unwindstack::AndroidRemoteUnwinder unwinder(forked_pid); for (pid_t tid : tids) { - DumpThread(forked_pid, tid, addr2line_path.get(), " ", backtrace_map.get()); + DumpThread(unwinder, forked_pid, tid, addr2line_path.get(), " "); } } diff --git a/tools/tracefast-plugin/tracefast.cc b/tools/tracefast-plugin/tracefast.cc index 618742de9a..abc871d9b3 100644 --- a/tools/tracefast-plugin/tracefast.cc +++ b/tools/tracefast-plugin/tracefast.cc @@ -60,7 +60,6 @@ class Tracer final : public art::instrumentation::InstrumentationListener { override REQUIRES_SHARED(art::Locks::mutator_lock_) { } void MethodUnwind(art::Thread* thread ATTRIBUTE_UNUSED, - art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED, art::ArtMethod* method ATTRIBUTE_UNUSED, uint32_t dex_pc ATTRIBUTE_UNUSED) override REQUIRES_SHARED(art::Locks::mutator_lock_) { } @@ -131,7 +130,8 @@ static void StartTracing() REQUIRES(!art::Locks::mutator_lock_, art::instrumentation::Instrumentation::kMethodEntered | art::instrumentation::Instrumentation::kMethodExited | art::instrumentation::Instrumentation::kMethodUnwind); - runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey, kNeedsInterpreter); + runtime->GetInstrumentation()->EnableMethodTracing( + kTracerInstrumentationKey, &gEmptyTracer, kNeedsInterpreter); } class TraceFastPhaseCB : public art::RuntimePhaseCallback { diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp index d5f5162419..7b120cfcc4 100644 --- a/tools/veridex/Android.bp +++ b/tools/veridex/Android.bp @@ -40,6 +40,7 @@ cc_binary { static_libs: [ "libdexfile", "libartbase", + "libartpalette", "libbase", "liblog", "libz", diff --git a/tools/veridex/Android.mk b/tools/veridex/Android.mk index f7c8d5084e..9ea9b3a5be 100644 --- a/tools/veridex/Android.mk +++ b/tools/veridex/Android.mk @@ -23,14 +23,14 @@ LOCAL_PATH := $(call my-dir) system_stub_dex := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/core_dex_intermediates/classes.dex $(system_stub_dex): PRIVATE_MIN_SDK_VERSION := 1000 -$(system_stub_dex): $(call resolve-prebuilt-sdk-jar-path,system_current) | $(ZIP2ZIP) $(DX) +$(system_stub_dex): $(call resolve-prebuilt-sdk-jar-path,system_current) | $(ZIP2ZIP) $(D8) $(transform-classes.jar-to-dex) $(call declare-1p-target,$(system_stub_dex),art) oahl_stub_dex := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/oahl_dex_intermediates/classes.dex $(oahl_stub_dex): PRIVATE_MIN_SDK_VERSION := 1000 -$(oahl_stub_dex): $(call get-prebuilt-sdk-dir,current)/org.apache.http.legacy.jar | $(ZIP2ZIP) $(DX) +$(oahl_stub_dex): $(call get-prebuilt-sdk-dir,current)/org.apache.http.legacy.jar | $(ZIP2ZIP) $(D8) $(transform-classes.jar-to-dex) $(call declare-1p-target,$(oahl_stub_dex),art) diff --git a/tools/veridex/flow_analysis.cc b/tools/veridex/flow_analysis.cc index 2a8b8a0522..6a4d3514d3 100644 --- a/tools/veridex/flow_analysis.cc +++ b/tools/veridex/flow_analysis.cc @@ -540,7 +540,7 @@ void VeriFlowAnalysis::ProcessDexInstruction(const Instruction& instruction) { case Instruction::FILLED_NEW_ARRAY: { dex::TypeIndex type_index(instruction.VRegB_35c()); VeriClass* cls = resolver_->GetVeriClass(type_index); - UpdateRegister(instruction.VRegA_22c(), cls); + UpdateRegister(instruction.VRegA_35c(), cls); break; } @@ -602,7 +602,7 @@ void VeriFlowAnalysis::ProcessDexInstruction(const Instruction& instruction) { if (VeriClass::sdkInt_ != nullptr && resolver_->GetField(field_index) == VeriClass::sdkInt_) { UpdateRegister(dest_reg, gTargetSdkVersion, VeriClass::integer_); } else { - UpdateRegister(dest_reg, GetFieldType(instruction.VRegC_22c())); + UpdateRegister(dest_reg, GetFieldType(field_index)); } break; } diff --git a/tools/veridex/hidden_api.cc b/tools/veridex/hidden_api.cc index 71ea56b56f..69e6fe403f 100644 --- a/tools/veridex/hidden_api.cc +++ b/tools/veridex/hidden_api.cc @@ -29,14 +29,22 @@ HiddenApi::HiddenApi(const char* filename, const ApiListFilter& api_list_filter) CHECK(filename != nullptr); std::ifstream in(filename); + bool errors = false; for (std::string str; std::getline(in, str);) { std::vector<std::string> values = android::base::Split(str, ","); const std::string& signature = values[0]; hiddenapi::ApiList membership; bool success = hiddenapi::ApiList::FromNames(values.begin() + 1, values.end(), &membership); - CHECK(success) << "Unknown ApiList flag: " << str; - CHECK(membership.IsValid()) << "Invalid ApiList: " << membership; + if (!success) { + LOG(ERROR) << "Unknown ApiList flag: " << str; + errors = true; + continue; + } else if (!membership.IsValid()) { + LOG(ERROR) << "Invalid ApiList: " << membership; + errors = true; + continue; + } AddSignatureToApiList(signature, membership); size_t pos = signature.find("->"); @@ -55,6 +63,7 @@ HiddenApi::HiddenApi(const char* filename, const ApiListFilter& api_list_filter) } } } + CHECK(!errors) << "Errors encountered while parsing file " << filename; } void HiddenApi::AddSignatureToApiList(const std::string& signature, hiddenapi::ApiList membership) { diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc index ae1c33e1d2..d2a32e6db1 100644 --- a/tools/veridex/veridex.cc +++ b/tools/veridex/veridex.cc @@ -19,6 +19,10 @@ #include <android-base/file.h> #include <android-base/strings.h> +#include <cstdlib> +#include <sstream> + +#include "base/mem_map.h" #include "dex/dex_file.h" #include "dex/dex_file_loader.h" #include "hidden_api.h" @@ -26,9 +30,6 @@ #include "precise_hidden_api_finder.h" #include "resolver.h" -#include <cstdlib> -#include <sstream> - namespace art { static VeriClass z_(Primitive::Type::kPrimBoolean, 0, nullptr); @@ -296,23 +297,18 @@ class Veridex { } // TODO: once added, use an api to android::base to read a std::vector<uint8_t>. - if (!android::base::ReadFileToString(filename.c_str(), &content)) { + if (!android::base::ReadFileToString(filename, &content)) { *error_msg = "ReadFileToString failed for " + filename; return false; } - const DexFileLoader dex_file_loader; DexFileLoaderErrorCode error_code; static constexpr bool kVerifyChecksum = true; static constexpr bool kRunDexFileVerifier = true; - if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()), - content.size(), - filename.c_str(), - kRunDexFileVerifier, - kVerifyChecksum, - &error_code, - error_msg, - dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast<const uint8_t*>(content.data()), content.size(), filename); + if (!dex_file_loader.Open( + kRunDexFileVerifier, kVerifyChecksum, &error_code, error_msg, dex_files)) { if (error_code == DexFileLoaderErrorCode::kEntryNotFound) { LOG(INFO) << "No .dex found, skipping analysis."; return true; @@ -343,5 +339,6 @@ class Veridex { } // namespace art int main(int argc, char** argv) { + art::MemMap::Init(); return art::Veridex::Run(argc, argv); } |