summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/art_method.cc17
-rw-r--r--runtime/art_method.h4
-rw-r--r--test/999-redefine-hiddenapi/api-blacklist.txt2
-rw-r--r--test/999-redefine-hiddenapi/build17
-rw-r--r--test/999-redefine-hiddenapi/expected.txt1
-rw-r--r--test/999-redefine-hiddenapi/info.txt1
-rwxr-xr-xtest/999-redefine-hiddenapi/run17
-rw-r--r--test/999-redefine-hiddenapi/src-ex/Test999.java25
-rw-r--r--test/999-redefine-hiddenapi/src-redefine/art/Test999.java25
-rwxr-xr-xtest/999-redefine-hiddenapi/src-redefine/gen.sh30
-rw-r--r--test/999-redefine-hiddenapi/src/Main.java111
-rw-r--r--test/999-redefine-hiddenapi/src/art/Redefinition.java91
-rwxr-xr-xtest/etc/default-build5
-rw-r--r--test/knownfailures.json11
14 files changed, 350 insertions, 7 deletions
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 41b01c251b..7030e0657b 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -710,6 +710,23 @@ bool ArtMethod::HasAnyCompiledCode() {
return GetOatMethodQuickCode(runtime->GetClassLinker()->GetImagePointerSize()) != nullptr;
}
+void ArtMethod::SetNotIntrinsic() {
+ if (!IsIntrinsic()) {
+ return;
+ }
+
+ // Query the hidden API access flags of the intrinsic.
+ HiddenApiAccessFlags::ApiList intrinsic_api_list = GetHiddenApiAccessFlags();
+
+ // Clear intrinsic-related access flags.
+ ClearAccessFlags(kAccIntrinsic | kAccIntrinsicBits);
+
+ // Re-apply hidden API access flags now that the method is not an intrinsic.
+ SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(GetAccessFlags(), intrinsic_api_list));
+ DCHECK_EQ(GetHiddenApiAccessFlags(), intrinsic_api_list);
+}
+
+
void ArtMethod::CopyFrom(ArtMethod* src, PointerSize image_pointer_size) {
memcpy(reinterpret_cast<void*>(this), reinterpret_cast<const void*>(src),
Size(image_pointer_size));
diff --git a/runtime/art_method.h b/runtime/art_method.h
index acaa4a68a1..012d706756 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -194,9 +194,7 @@ class ArtMethod FINAL {
return (GetAccessFlags() & kAccIntrinsicBits) >> kAccFlagsShift;
}
- void SetNotIntrinsic() REQUIRES_SHARED(Locks::mutator_lock_) {
- ClearAccessFlags(kAccIntrinsic | kAccIntrinsicBits);
- }
+ void SetNotIntrinsic() REQUIRES_SHARED(Locks::mutator_lock_);
bool IsCopied() {
static_assert((kAccCopied & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
diff --git a/test/999-redefine-hiddenapi/api-blacklist.txt b/test/999-redefine-hiddenapi/api-blacklist.txt
new file mode 100644
index 0000000000..63e37aa757
--- /dev/null
+++ b/test/999-redefine-hiddenapi/api-blacklist.txt
@@ -0,0 +1,2 @@
+Lart/Test999;->foo()V
+Lart/Test999;->bar:I
diff --git a/test/999-redefine-hiddenapi/build b/test/999-redefine-hiddenapi/build
new file mode 100644
index 0000000000..f4b029fb82
--- /dev/null
+++ b/test/999-redefine-hiddenapi/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2018 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.
+
+USE_HIDDENAPI=true ./default-build "$@"
diff --git a/test/999-redefine-hiddenapi/expected.txt b/test/999-redefine-hiddenapi/expected.txt
new file mode 100644
index 0000000000..6a5618ebc6
--- /dev/null
+++ b/test/999-redefine-hiddenapi/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/999-redefine-hiddenapi/info.txt b/test/999-redefine-hiddenapi/info.txt
new file mode 100644
index 0000000000..87bc30cf80
--- /dev/null
+++ b/test/999-redefine-hiddenapi/info.txt
@@ -0,0 +1 @@
+Tests that JVMTI class redefinition does not strip away hidden API access flags.
diff --git a/test/999-redefine-hiddenapi/run b/test/999-redefine-hiddenapi/run
new file mode 100755
index 0000000000..c6e62ae6cd
--- /dev/null
+++ b/test/999-redefine-hiddenapi/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+./default-run "$@" --jvmti
diff --git a/test/999-redefine-hiddenapi/src-ex/Test999.java b/test/999-redefine-hiddenapi/src-ex/Test999.java
new file mode 100644
index 0000000000..97495c5a47
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src-ex/Test999.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 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 art;
+
+public class Test999 {
+ public void foo() {
+ System.out.println("hello");
+ }
+
+ public int bar = 42;
+}
diff --git a/test/999-redefine-hiddenapi/src-redefine/art/Test999.java b/test/999-redefine-hiddenapi/src-redefine/art/Test999.java
new file mode 100644
index 0000000000..c1b838ccc7
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src-redefine/art/Test999.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 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 art;
+
+public class Test999 {
+ public void foo() {
+ System.out.println("Goodbye");
+ }
+
+ public int bar = 64;
+}
diff --git a/test/999-redefine-hiddenapi/src-redefine/gen.sh b/test/999-redefine-hiddenapi/src-redefine/gen.sh
new file mode 100755
index 0000000000..6948cbbfc3
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src-redefine/gen.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright 2018 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
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+TMP=`mktemp -d`
+
+CLASS "art/Test999"
+
+(cd "$TMP" && javac -d "${TMP}" "$DIR/${CLASS}.java" && d8 --output . "$TMP/${CLASS}.class")
+
+echo ' private static final byte[] CLASS_BYTES = Base64.getDecoder().decode('
+base64 "${TMP}/${CLASS}.class" | sed -E 's/^/ "/' | sed ':a;N;$!ba;s/\n/" +\n/g' | sed -E '$ s/$/");/'
+echo ' private static final byte[] DEX_BYTES = Base64.getDecoder().decode('
+base64 "${TMP}/classes.dex" | sed -E 's/^/ "/' | sed ':a;N;$!ba;s/\n/" +\n/g' | sed -E '$ s/$/");/'
+
+rm -rf "$TMP"
diff --git a/test/999-redefine-hiddenapi/src/Main.java b/test/999-redefine-hiddenapi/src/Main.java
new file mode 100644
index 0000000000..c6365ac234
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src/Main.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 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 java.io.File;
+import java.lang.reflect.Method;
+import java.util.Base64;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+
+ // Run the initialization routine. This will enable hidden API checks in
+ // the runtime, in case they are not enabled by default.
+ init();
+
+ // Load the '-ex' APK and attach it to the boot class path.
+ appendToBootClassLoader(DEX_EXTRA);
+
+ // Find the test class in boot class loader and verify that its members are hidden.
+ Class<?> klass = Class.forName("art.Test999", true, BOOT_CLASS_LOADER);
+ assertMethodIsHidden(klass, "before redefinition");
+ assertFieldIsHidden(klass, "before redefinition");
+
+ // Redefine the class using JVMTI.
+ art.Redefinition.setTestConfiguration(art.Redefinition.Config.COMMON_REDEFINE);
+ art.Redefinition.doCommonClassRedefinition(klass, CLASS_BYTES, DEX_BYTES);
+
+ // Verify that the class members are still hidden.
+ assertMethodIsHidden(klass, "after redefinition");
+ assertFieldIsHidden(klass, "after redefinition");
+ }
+
+ private static void assertMethodIsHidden(Class<?> klass, String msg) throws Exception {
+ try {
+ klass.getDeclaredMethod("foo");
+ // Unexpected. Should have thrown NoSuchMethodException.
+ throw new Exception("Method should not be accessible " + msg);
+ } catch (NoSuchMethodException ex) {
+ // Expected.
+ }
+ }
+
+ private static void assertFieldIsHidden(Class<?> klass, String msg) throws Exception {
+ try {
+ klass.getDeclaredField("bar");
+ // Unexpected. Should have thrown NoSuchFieldException.
+ throw new Exception("Field should not be accessible " + msg);
+ } catch (NoSuchFieldException ex) {
+ // Expected.
+ }
+ }
+
+ private static final String DEX_EXTRA =
+ new File(System.getenv("DEX_LOCATION"), "999-redefine-hiddenapi-ex.jar").getAbsolutePath();
+
+ private static ClassLoader BOOT_CLASS_LOADER = Object.class.getClassLoader();
+
+ // Native functions. Note that these are implemented in 674-hiddenapi/hiddenapi.cc.
+ private static native void appendToBootClassLoader(String dexPath);
+ private static native void init();
+
+ /**
+ * base64 encoded class/dex file for
+ *
+ * public class Test999 {
+ * public void foo() {
+ * System.out.println("Goodbye");
+ * }
+ *
+ * public int bar = 64;
+ * }
+ */
+ private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
+ "yv66vgAAADUAIAoABwARCQAGABIJABMAFAgAFQoAFgAXBwAYBwAZAQADYmFyAQABSQEABjxpbml0" +
+ "PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAANmb28BAApTb3VyY2VGaWxlAQAMVGVz" +
+ "dDk5OS5qYXZhDAAKAAsMAAgACQcAGgwAGwAcAQAHR29vZGJ5ZQcAHQwAHgAfAQALYXJ0L1Rlc3Q5" +
+ "OTkBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lv" +
+ "L1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xh" +
+ "bmcvU3RyaW5nOylWACEABgAHAAAAAQABAAgACQAAAAIAAQAKAAsAAQAMAAAAJwACAAEAAAALKrcA" +
+ "ASoQQLUAArEAAAABAA0AAAAKAAIAAAATAAQAGAABAA4ACwABAAwAAAAlAAIAAQAAAAmyAAMSBLYA" +
+ "BbEAAAABAA0AAAAKAAIAAAAVAAgAFgABAA8AAAACABA=");
+ private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
+ "ZGV4CjAzNQD0dZ+IWxOi+cJDSWjfTnUerlZj1Lll3ONIAwAAcAAAAHhWNBIAAAAAAAAAAJwCAAAQ" +
+ "AAAAcAAAAAcAAACwAAAAAgAAAMwAAAACAAAA5AAAAAQAAAD0AAAAAQAAABQBAAAUAgAANAEAAIYB" +
+ "AACOAQAAlwEAAJoBAACpAQAAwAEAANQBAADoAQAA/AEAAAoCAAANAgAAEQIAABYCAAAbAgAAIAIA" +
+ "ACkCAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAJAAAACQAAAAYAAAAAAAAACgAAAAYAAACAAQAA" +
+ "AQAAAAsAAAAFAAIADQAAAAEAAAAAAAAAAQAAAAwAAAACAAEADgAAAAMAAAAAAAAAAQAAAAEAAAAD" +
+ "AAAAAAAAAAgAAAAAAAAAhwIAAAAAAAACAAEAAQAAAHQBAAAIAAAAcBADAAEAEwBAAFkQAAAOAAMA" +
+ "AQACAAAAeQEAAAgAAABiAAEAGgEBAG4gAgAQAA4AEwAOQAAVAA54AAAAAQAAAAQABjxpbml0PgAH" +
+ "R29vZGJ5ZQABSQANTGFydC9UZXN0OTk5OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9s" +
+ "YW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAxUZXN0" +
+ "OTk5LmphdmEAAVYAAlZMAANiYXIAA2ZvbwADb3V0AAdwcmludGxuAFx+fkQ4eyJtaW4tYXBpIjox" +
+ "LCJzaGEtMSI6IjU2YzJlMzBmNTIzM2I4NDRmZjZkZGQ4N2ZiNTNkMzRmYjE3MjM3ZGYiLCJ2ZXJz" +
+ "aW9uIjoidjEuMi4xNS1kZXYifQAAAQEBAAEAgYAEtAIBAdQCAAAAAAAOAAAAAAAAAAEAAAAAAAAA" +
+ "AQAAABAAAABwAAAAAgAAAAcAAACwAAAAAwAAAAIAAADMAAAABAAAAAIAAADkAAAABQAAAAQAAAD0" +
+ "AAAABgAAAAEAAAAUAQAAASAAAAIAAAA0AQAAAyAAAAIAAAB0AQAAARAAAAEAAACAAQAAAiAAABAA" +
+ "AACGAQAAACAAAAEAAACHAgAAAxAAAAEAAACYAgAAABAAAAEAAACcAgAA");
+}
diff --git a/test/999-redefine-hiddenapi/src/art/Redefinition.java b/test/999-redefine-hiddenapi/src/art/Redefinition.java
new file mode 100644
index 0000000000..1eec70b48c
--- /dev/null
+++ b/test/999-redefine-hiddenapi/src/art/Redefinition.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 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 art;
+
+import java.util.ArrayList;
+// Common Redefinition functions. Placed here for use by CTS
+public class Redefinition {
+ public static final class CommonClassDefinition {
+ public final Class<?> target;
+ public final byte[] class_file_bytes;
+ public final byte[] dex_file_bytes;
+
+ public CommonClassDefinition(Class<?> target, byte[] class_file_bytes, byte[] dex_file_bytes) {
+ this.target = target;
+ this.class_file_bytes = class_file_bytes;
+ this.dex_file_bytes = dex_file_bytes;
+ }
+ }
+
+ // A set of possible test configurations. Test should set this if they need to.
+ // This must be kept in sync with the defines in ti-agent/common_helper.cc
+ public static enum Config {
+ COMMON_REDEFINE(0),
+ COMMON_RETRANSFORM(1),
+ COMMON_TRANSFORM(2);
+
+ private final int val;
+ private Config(int val) {
+ this.val = val;
+ }
+ }
+
+ public static void setTestConfiguration(Config type) {
+ nativeSetTestConfiguration(type.val);
+ }
+
+ private static native void nativeSetTestConfiguration(int type);
+
+ // Transforms the class
+ public static native void doCommonClassRedefinition(Class<?> target,
+ byte[] classfile,
+ byte[] dexfile);
+
+ public static void doMultiClassRedefinition(CommonClassDefinition... defs) {
+ ArrayList<Class<?>> classes = new ArrayList<>();
+ ArrayList<byte[]> class_files = new ArrayList<>();
+ ArrayList<byte[]> dex_files = new ArrayList<>();
+
+ for (CommonClassDefinition d : defs) {
+ classes.add(d.target);
+ class_files.add(d.class_file_bytes);
+ dex_files.add(d.dex_file_bytes);
+ }
+ doCommonMultiClassRedefinition(classes.toArray(new Class<?>[0]),
+ class_files.toArray(new byte[0][]),
+ dex_files.toArray(new byte[0][]));
+ }
+
+ public static void addMultiTransformationResults(CommonClassDefinition... defs) {
+ for (CommonClassDefinition d : defs) {
+ addCommonTransformationResult(d.target.getCanonicalName(),
+ d.class_file_bytes,
+ d.dex_file_bytes);
+ }
+ }
+
+ public static native void doCommonMultiClassRedefinition(Class<?>[] targets,
+ byte[][] classfiles,
+ byte[][] dexfiles);
+ public static native void doCommonClassRetransformation(Class<?>... target);
+ public static native void setPopRetransformations(boolean pop);
+ public static native void popTransformationFor(String name);
+ public static native void enableCommonRetransformation(boolean enable);
+ public static native void addCommonTransformationResult(String target_name,
+ byte[] class_bytes,
+ byte[] dex_bytes);
+}
diff --git a/test/etc/default-build b/test/etc/default-build
index 3e6577cfda..4d3ff8b26a 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -543,6 +543,11 @@ fi
if [[ -d classes-ex ]] && [ ${NEED_DEX} = "true" ]; then
make_dex classes-ex
+ # Apply hiddenapi on the dex files if the test has API list file(s).
+ if [ ${USE_HIDDENAPI} = "true" -a ${HAS_HIDDENAPI_SPEC} = "true" ]; then
+ make_hiddenapi classes-ex.dex
+ fi
+
# quick shuffle so that the stored name is "classes.dex"
mv classes.dex classes-1.dex
mv classes-ex.dex classes.dex
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 436ab318ad..43f4c1d310 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -469,7 +469,8 @@
"674-hiddenapi",
"649-vdex-duplicate-method",
"804-class-extends-itself",
- "921-hello-failure"
+ "921-hello-failure",
+ "999-redefine-hiddenapi"
],
"description": [
"Tests that use illegal dex files or otherwise break dexter assumptions"
@@ -486,7 +487,8 @@
"629-vdex-speed",
"647-jni-get-field-id",
"674-hiddenapi",
- "944-transform-classloaders"
+ "944-transform-classloaders",
+ "999-redefine-hiddenapi"
],
"description": [
"Tests that use custom class loaders or other features not supported ",
@@ -895,7 +897,6 @@
"667-jit-jni-stub",
"667-out-of-bounds",
"668-aiobe",
- "674-hiddenapi",
"674-hotness-compiled",
"674-vdex-uncompress",
"675-checker-unverified-method",
@@ -973,8 +974,10 @@
},
{
"tests": ["616-cha-unloading",
+ "674-hiddenapi",
"678-quickening",
- "679-locks"],
+ "679-locks",
+ "999-redefine-hiddenapi"],
"variant": "jvm",
"description": ["Doesn't run on RI."]
},