Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the AOSP9 #372

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
269 changes: 269 additions & 0 deletions jni/art/art_9_0.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
/*
*
* Copyright (c) 2011 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.
*/

/**
* Created by Tanck 11/14/2020 11:31PM
*
* http://androidxref.com/9.0.0_r3/xref/art/runtime/mirror/class.h
* http://androidxref.com/9.0.0_r3/xref/art/runtime/art_field.h
* http://androidxref.com/9.0.0_r3/xref/art/runtime/art_method.h
*/
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <string>
#include <memory>
#include <sys/mman.h>

#include <fcntl.h>
#include <dlfcn.h>

#include <stdint.h> /* C99 */

namespace art {
namespace mirror {
class Object {
public:
// The number of vtable entries in java.lang.Object.
static constexpr size_t kVTableLength = 11;
static uint32_t hash_code_seed;
uint32_t klass_;
uint32_t monitor_;
};

class Class : public Object {
public:
enum {
kDumpClassFullDetail = 1,
kDumpClassClassLoader = (1 << 1),
kDumpClassInitialized = (1 << 2),
};

// A magic value for reference_instance_offsets_. Ignore the bits and walk the super chain when
// this is the value.
// [This is an unlikely "natural" value, since it would be 30 non-ref instance fields followed by
// 2 ref instance fields.]
static constexpr uint32_t kClassWalkSuper = 0xC0000000;
// Shift primitive type by kPrimitiveTypeSizeShiftShift to get the component type size shift
// Used for computing array size as follows:
// array_bytes = header_size + (elements << (primitive_type >> kPrimitiveTypeSizeShiftShift))
static constexpr uint32_t kPrimitiveTypeSizeShiftShift = 16;
static constexpr uint32_t kPrimitiveTypeMask = (1u << kPrimitiveTypeSizeShiftShift) - 1;

// 'Class' Object Fields
// Order governed by java field ordering. See art::ClassLinker::LinkFields.

// Defining class loader, or null for the "bootstrap" system loader.
uint32_t class_loader_;
// For array classes, the component class object for instanceof/checkcast
// (for String[][][], this will be String[][]). null for non-array classes.
uint32_t component_type_;
// DexCache of resolved constant pool entries (will be null for classes generated by the
// runtime such as arrays and primitive classes).
uint32_t dex_cache_;
// Extraneous class data that is not always needed. This field is allocated lazily and may
// only be set with 'this' locked. This is synchronized on 'this'.
// TODO(allight) We should probably synchronize it on something external or handle allocation in
// some other (safe) way to prevent possible deadlocks.
uint32_t ext_data_;

// The interface table (iftable_) contains pairs of a interface class and an array of the
// interface methods. There is one pair per interface supported by this class. That means one
// pair for each interface we support directly, indirectly via superclass, or indirectly via a
// superinterface. This will be null if neither we nor our superclass implement any interfaces.
//
// Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()".
// Invoke faceObj.blah(), where "blah" is part of the Face interface. We can't easily use a
// single vtable.
//
// For every interface a concrete class implements, we create an array of the concrete vtable_
// methods for the methods in the interface.
uint32_t iftable_;
// Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
uint32_t name_;
// The superclass, or null if this is java.lang.Object or a primitive type.
//
// Note that interfaces have java.lang.Object as their
// superclass. This doesn't match the expectations in JNI
// GetSuperClass or java.lang.Class.getSuperClass() which need to
// check for interfaces and return null.
uint32_t super_class_;
// Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is
// copied in, and virtual methods from our class either replace those from the super or are
// appended. For abstract classes, methods may be created in the vtable that aren't in
// virtual_ methods_ for miranda methods.
uint32_t vtable_;
// instance fields
//
// These describe the layout of the contents of an Object.
// Note that only the fields directly declared by this class are
// listed in ifields; fields declared by a superclass are listed in
// the superclass's Class.ifields.
//
// ArtFields are allocated as a length prefixed ArtField array, and not an array of pointers to
// ArtFields.
uint64_t ifields_;
// Pointer to an ArtMethod length-prefixed array. All the methods where this class is the place
// where they are logically defined. This includes all private, static, final and virtual methods
// as well as inherited default methods and miranda methods.
//
// The slice methods_ [0, virtual_methods_offset_) are the direct (static, private, init) methods
// declared by this class.
//
// The slice methods_ [virtual_methods_offset_, copied_methods_offset_) are the virtual methods
// declared by this class.
//
// The slice methods_ [copied_methods_offset_, |methods_|) are the methods that are copied from
// interfaces such as miranda or default methods. These are copied for resolution purposes as this
// class is where they are (logically) declared as far as the virtual dispatch is concerned.
//
// Note that this field is used by the native debugger as the unique identifier for the type.
uint64_t methods_;
// Static fields length-prefixed array.
uint64_t sfields_;
// Access flags; low 16 bits are defined by VM spec.
uint32_t access_flags_;
// Class flags to help speed up visiting object references.
uint32_t class_flags_;

// Total size of the Class instance; used when allocating storage on gc heap.
// See also object_size_.
uint32_t class_size_;

// Tid used to check for recursive <clinit> invocation.
pid_t clinit_thread_id_;

// ClassDef index in dex file, -1 if no class definition such as an array.
// TODO: really 16bits
int32_t dex_class_def_idx_;

// Type index in dex file.
// TODO: really 16bits
int32_t dex_type_idx_;

// Number of instance fields that are object refs.
uint32_t num_reference_instance_fields_;

// Number of static fields that are object refs,
uint32_t num_reference_static_fields_;

// Total object size; used when allocating storage on gc heap.
// (For interfaces and abstract classes this will be zero.)
// See also class_size_.
uint32_t object_size_;

// Aligned object size for allocation fast path. The value is max uint32_t if the object is
// uninitialized or finalizable. Not currently used for variable sized objects.
uint32_t object_size_alloc_fast_path_;

// The lower 16 bits contains a Primitive::Type value. The upper 16
// bits contains the size shift of the primitive type.
uint32_t primitive_type_;

// Bitmap of offsets of ifields.
uint32_t reference_instance_offsets_;

// See the real definition in subtype_check_bits_and_status.h
// typeof(status_) is actually SubtypeCheckBitsAndStatus.
uint32_t status_;

// The offset of the first virtual method that is copied from an interface. This includes miranda,
// default, and default-conflict methods. Having a hard limit of ((2 << 16) - 1) for methods
// defined on a single class is well established in Java so we will use only uint16_t's here.
uint16_t copied_methods_offset_;

// The offset of the first declared virtual methods in the methods_ array.
uint16_t virtual_methods_offset_;

// TODO: ?
// initiating class loader list
// NOTE: for classes with low serialNumber, these are unused, and the
// values are kept in a table in gDvm.
// InitiatingLoaderList initiating_loader_list_;

// The following data exist in real class objects.
// Embedded Imtable, for class object that's not an interface, fixed size.
// ImTableEntry embedded_imtable_[0];
// Embedded Vtable, for class object that's not an interface, variable size.
// VTableEntry embedded_vtable_[0];
// Static fields, variable size.
// uint32_t fields_[0];

// java.lang.Class
static uint32_t java_lang_Class_;

};

class ArtField {
public:
uint32_t declaring_class_;
uint32_t access_flags_;
uint32_t field_dex_idx_;
uint32_t offset_;
};

class ArtMethod {
public:

// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class we are a part of.
uint32_t declaring_class_;

// Access flags; low 16 bits are defined by spec.
// Getting and setting this flag needs to be atomic when concurrency is
// possible, e.g. after this method's class is linked. Such as when setting
// verifier flags and single-implementation flag.
uint32_t access_flags_;

/* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */

// Offset to the CodeItem.
uint32_t dex_code_item_offset_;

// Index into method_ids of the dex file associated with this method.
uint32_t dex_method_index_;

/* End of dex file fields. */

// Entry within a dispatch table for this method. For static/direct methods the index is into
// the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
// ifTable.
uint16_t method_index_;

// The hotness we measure for this method. Not atomic, as we allow
// missing increments: if the method is hot, we will see it eventually.
uint16_t hotness_count_;
struct PtrSizedFields {
// Depending on the method type, the data is
// - native method: pointer to the JNI function registered to this method
// or a function to resolve the JNI function,
// - conflict method: ImtConflictTable,
// - abstract/interface method: the single-implementation if any,
// - proxy method: the original interface method or constructor,
// - other methods: the profiling data.
void *data_;

// Method dispatch from quick compiled code invokes this pointer which may cause bridging into
// the interpreter.
void *entry_point_from_quick_compiled_code_;
} ptr_sized_fields_;

};

}

}
10 changes: 7 additions & 3 deletions jni/art/art_method_replace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ extern jboolean __attribute__ ((visibility ("hidden"))) art_setup(JNIEnv* env,

extern void __attribute__ ((visibility ("hidden"))) art_replaceMethod(
JNIEnv* env, jobject src, jobject dest) {
if (apilevel > 23) {
if (apilevel == 28) {
replace_9_0(env, src, dest);
} else if (apilevel == 24) {
replace_7_0(env, src, dest);
} else if (apilevel > 22) {
replace_6_0(env, src, dest);
Expand All @@ -67,8 +69,10 @@ extern void __attribute__ ((visibility ("hidden"))) art_replaceMethod(

extern void __attribute__ ((visibility ("hidden"))) art_setFieldFlag(
JNIEnv* env, jobject field) {
if (apilevel > 23) {
setFieldFlag_7_0(env, field);
if (apilevel == 28) {
setFieldFlag_9_0(env, field);
} else if (apilevel == 24) {
setFieldFlag_7_0(env, field);
} else if (apilevel > 22) {
setFieldFlag_6_0(env, field);
} else if (apilevel > 21) {
Expand Down
74 changes: 74 additions & 0 deletions jni/art/art_method_replace_9_0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
*
* 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.
*/

/**
* art_method_replace_9_0.cpp
* Created by Tanck 11/14/2020 11:31PM
*/

#pragma ide diagnostic ignored "hicpp-signed-bitwise"
#include <ctime>
#include <cstdlib>
#include <cstddef>
#include <cassert>
#include <fcntl.h>
#include <dlfcn.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <cctype>
#include <cerrno>
#include <utime.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "art.h"
#include "art_9_0.h"
#include "../common.h"

/**
* Replace the method on android9
* @param env the native env
* @param src the bug method
* @param dest the fixed method
*/
void replace_9_0(JNIEnv *env, jobject src, jobject dest) {
auto *source_method = (art::mirror::ArtMethod *) env->FromReflectedMethod(src);
auto *dest_method = (art::mirror::ArtMethod *) env->FromReflectedMethod(dest);

reinterpret_cast<art::mirror::Class *>(dest_method->declaring_class_)->clinit_thread_id_ = reinterpret_cast<art::mirror::Class *>(source_method->declaring_class_)->clinit_thread_id_;
reinterpret_cast<art::mirror::Class *>(dest_method->declaring_class_)->status_ = reinterpret_cast<art::mirror::Class *>(source_method->declaring_class_)->status_ - 1;
reinterpret_cast<art::mirror::Class *>(dest_method->declaring_class_)->super_class_ = 0;

source_method->declaring_class_ = dest_method->declaring_class_;
source_method->access_flags_ = dest_method->access_flags_ | 0x0001;
source_method->dex_code_item_offset_ = dest_method->dex_code_item_offset_;
source_method->dex_method_index_ = dest_method->dex_method_index_;
source_method->method_index_ = dest_method->method_index_;
source_method->hotness_count_ = dest_method->hotness_count_;
source_method->ptr_sized_fields_.data_ = dest_method->ptr_sized_fields_.data_;
source_method->ptr_sized_fields_.entry_point_from_quick_compiled_code_ = dest_method->ptr_sized_fields_.entry_point_from_quick_compiled_code_;

LOGD("replace_9_0: %d , %d",
source_method->ptr_sized_fields_.entry_point_from_quick_compiled_code_,
dest_method->ptr_sized_fields_.entry_point_from_quick_compiled_code_);

}

void setFieldFlag_9_0(JNIEnv *env, jobject field) {
auto *artField = (art::mirror::ArtField *) env->FromReflectedField(field);
artField->access_flags_ = artField->access_flags_ & (~0x0002) | 0x0001;
LOGD("setFieldFlag_9_0: %d ", artField->access_flags_);
}