Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import android.content.pm.ApplicationInfo;
import android.graphics.drawable.ClipDrawable;
import android.os.Build;
import android.os.Process;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SdkSuppress;
Expand Down Expand Up @@ -165,20 +164,14 @@ class X {
public void PtestCachedOffset() {
var context = InstrumentationRegistry.getInstrumentation().getContext();
var artVersion = Helper.getArtVersion(context);
var isOld = artVersion == -1L;
var isNew = artVersion >= 36_00_00000L;
var is64bit = Process.is64Bit();
var data = new long[10];
var data = new long[6];
data[0] = 24;
data[1] = 12;
data[2] = 24;
data[3] = 48;
data[4] = 40;
data[5] = isNew ? 40 : 56;
data[6] = isOld ? is64bit ? 40 : 28 : is64bit ? 32 : 24;
data[7] = is64bit ? 8 : 4;
data[8] = 16;
data[9] = 4;
assertArrayEquals("art version " + artVersion, data, Helper.getCachedOffsetData());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public static long[] getCachedOffsetData() {
}

public static void setCachedOffsetData(long[] data) {
if (cachedOffsetData != null || data.length != 10) return;
if (cachedOffsetData != null || data.length != 6) return;
cachedOffsetData = data;

if (cacheFile == null) return;
Expand All @@ -63,6 +63,7 @@ public static void setCachedOffsetData(long[] data) {
}

public static void enableOffsetCache(Context context) {
if (cacheFile != null) return;
cacheFile = new File(context.getCacheDir(), "HiddenApiBypass");
artVersion = getArtVersion(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public final class HiddenApiBypass {
unsafe = (Unsafe) Unsafe.class.getDeclaredMethod("getUnsafe").invoke(null);
var data = Helper.getCachedOffsetData();
if (data == null) {
data = readOffsetData();
data = readOffsetDataIO();
Helper.setCachedOffsetData(data);
} else if (BuildConfig.DEBUG) {
Log.d(TAG, "Using cached offset data");
Expand All @@ -74,18 +74,18 @@ public final class HiddenApiBypass {
methodsOffset = data[3];
iFieldOffset = data[4];
sFieldOffset = data[5];
artMethodSize = data[6];
artMethodBias = data[7];
artFieldSize = data[8];
artFieldBias = data[9];
var dataRT = readOffsetDataRT();
artMethodSize = dataRT[0];
artMethodBias = dataRT[1];
artFieldSize = dataRT[2];
artFieldBias = dataRT[3];
} catch (ReflectiveOperationException e) {
Log.e(TAG, "Initialize error", e);
throw new ExceptionInInitializerError(e);
}

}

private static long[] readOffsetData() throws ReflectiveOperationException {
private static long[] readOffsetDataIO() throws ReflectiveOperationException {
ClassLoader bootClassloader = new CoreOjClassLoader();
Class<?> executableClass = bootClassloader.loadClass(Executable.class.getName());
Class<?> methodHandleClass = bootClassloader.loadClass(MethodHandle.class.getName());
Expand All @@ -95,16 +95,27 @@ private static long[] readOffsetData() throws ReflectiveOperationException {
var artOffset = unsafe.objectFieldOffset(methodHandleClass.getDeclaredField("artFieldOrMethod"));
var methodsOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("methods"));

long iField;
long sField;
long iFieldOffset;
long sFieldOffset;
try {
iField = unsafe.objectFieldOffset(classClass.getDeclaredField("fields"));
sField = iField;
iFieldOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("fields"));
sFieldOffset = iFieldOffset;
} catch (NoSuchFieldException e) {
iField = unsafe.objectFieldOffset(classClass.getDeclaredField("iFields"));
sField = unsafe.objectFieldOffset(classClass.getDeclaredField("sFields"));
iFieldOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("iFields"));
sFieldOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("sFields"));
}

long[] data = new long[6];
data[0] = methodOffset;
data[1] = classOffset;
data[2] = artOffset;
data[3] = methodsOffset;
data[4] = iFieldOffset;
data[5] = sFieldOffset;
return data;
}

private static long[] readOffsetDataRT() throws ReflectiveOperationException {
Method mA = Helper.NeverCall.class.getDeclaredMethod("a");
Method mB = Helper.NeverCall.class.getDeclaredMethod("b");
mA.setAccessible(true);
Expand All @@ -129,25 +140,19 @@ private static long[] readOffsetData() throws ReflectiveOperationException {
MethodHandle mhJ = MethodHandles.lookup().unreflectGetter(fJ);
long iAddr = unsafe.getLong(mhI, artOffset);
long jAddr = unsafe.getLong(mhJ, artOffset);
long iFields = unsafe.getLong(Helper.NeverCall.class, iField);
long iFields = unsafe.getLong(Helper.NeverCall.class, iFieldOffset);
var artFieldSize = jAddr - iAddr;
if (BuildConfig.DEBUG) Log.v(TAG, artFieldSize + " " +
Long.toString(iAddr, 16) + ", " +
Long.toString(jAddr, 16) + ", " +
Long.toString(iFields, 16));
var artFieldBias = iAddr - iFields;

long[] data = new long[10];
data[0] = methodOffset;
data[1] = classOffset;
data[2] = artOffset;
data[3] = methodsOffset;
data[4] = iField;
data[5] = sField;
data[6] = artMethodSize;
data[7] = artMethodBias;
data[8] = artFieldSize;
data[9] = artFieldBias;
long[] data = new long[4];
data[0] = artMethodSize;
data[1] = artMethodBias;
data[2] = artFieldSize;
data[3] = artFieldBias;
return data;
}

Expand Down