From 9323e6e44060545d6c4f925139572868f65b7fe3 Mon Sep 17 00:00:00 2001 From: David Sehr Date: Tue, 13 Sep 2016 08:58:35 -0700 Subject: [PATCH] Separate annotations from dexfile reading. Bug: 22322814 Change-Id: I867d66da407dd80394a10d19903ebbc1ec3986ff Test: test-art --- compiler/compiler.h | 4 + runtime/Android.bp | 1 + runtime/art_method-inl.h | 3 +- runtime/art_method.cc | 5 +- runtime/art_method.h | 1 + runtime/class_linker.cc | 7 +- runtime/debugger.cc | 5 +- runtime/dex_file.cc | 1271 +------------------ runtime/dex_file.h | 171 +-- runtime/dex_file_annotations.cc | 1303 ++++++++++++++++++++ runtime/dex_file_annotations.h | 125 ++ runtime/interpreter/unstarted_runtime.cc | 2 +- runtime/jit/jit.h | 1 + runtime/mirror/class.cc | 3 +- runtime/native/java_lang_Class.cc | 23 +- runtime/native/java_lang_reflect_AbstractMethod.cc | 14 +- runtime/native/java_lang_reflect_Constructor.cc | 3 +- runtime/native/java_lang_reflect_Field.cc | 10 +- runtime/native/java_lang_reflect_Method.cc | 5 +- runtime/native/java_lang_reflect_Parameter.cc | 3 +- runtime/quick/inline_method_analyser.h | 1 + runtime/quick_exception_handler.cc | 4 +- runtime/thread.cc | 5 +- 23 files changed, 1514 insertions(+), 1456 deletions(-) create mode 100644 runtime/dex_file_annotations.cc create mode 100644 runtime/dex_file_annotations.h diff --git a/compiler/compiler.h b/compiler/compiler.h index ed42958a7..9a69456b5 100644 --- a/compiler/compiler.h +++ b/compiler/compiler.h @@ -25,10 +25,14 @@ namespace art { namespace jit { class JitCodeCache; } +namespace mirror { + class DexCache; +} class ArtMethod; class CompilerDriver; class CompiledMethod; +template class Handle; class OatWriter; class Compiler { diff --git a/runtime/Android.bp b/runtime/Android.bp index b61976c47..eb7b0c82f 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -53,6 +53,7 @@ cc_defaults { "compiler_filter.cc", "debugger.cc", "dex_file.cc", + "dex_file_annotations.cc", "dex_file_verifier.cc", "dex_instruction.cc", "elf_file.cc", diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index 1659f3333..9b4b38aa0 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -24,6 +24,7 @@ #include "class_linker-inl.h" #include "common_throws.h" #include "dex_file.h" +#include "dex_file_annotations.h" #include "dex_file-inl.h" #include "gc_root-inl.h" #include "jit/profiling_info.h" @@ -347,7 +348,7 @@ inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) { if (dex_pc == DexFile::kDexNoIndex) { return IsNative() ? -2 : -1; } - return GetDexFile()->GetLineNumFromPC(this, dex_pc); + return annotations::GetLineNumFromPC(GetDexFile(), this, dex_pc); } inline const DexFile::ProtoId& ArtMethod::GetPrototype() { diff --git a/runtime/art_method.cc b/runtime/art_method.cc index 1392399bd..78eea185a 100644 --- a/runtime/art_method.cc +++ b/runtime/art_method.cc @@ -25,6 +25,7 @@ #include "class_linker-inl.h" #include "debugger.h" #include "dex_file-inl.h" +#include "dex_file_annotations.h" #include "dex_instruction.h" #include "entrypoints/runtime_asm_entrypoints.h" #include "gc/accounting/card_table-inl.h" @@ -349,8 +350,6 @@ bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) { ScopedObjectAccess soa(self); StackHandleScope<1> shs(self); - const DexFile& dex_file = GetDeclaringClass()->GetDexFile(); - mirror::Class* annotation = soa.Decode(klass); DCHECK(annotation->IsAnnotation()); Handle annotation_handle(shs.NewHandle(annotation)); @@ -358,7 +357,7 @@ bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) { // Note: Resolves any method annotations' classes as a side-effect. // -- This seems allowed by the spec since it says we can preload any classes // referenced by another classes's constant pool table. - return dex_file.IsMethodAnnotationPresent(this, annotation_handle, visibility); + return annotations::IsMethodAnnotationPresent(this, annotation_handle, visibility); } bool ArtMethod::EqualParameters(Handle> params) { diff --git a/runtime/art_method.h b/runtime/art_method.h index 8051a1fc7..b1baccded 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -33,6 +33,7 @@ namespace art { +template class Handle; union JValue; class OatQuickMethodHeader; class ProfilingInfo; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 4d252e1be..cf7942c01 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -4639,8 +4639,11 @@ bool ClassLinker::InitializeClass(Thread* self, Handle klass, } } - EncodedStaticFieldValueIterator value_it(dex_file, &dex_cache, &class_loader, - this, *dex_class_def); + annotations::RuntimeEncodedStaticFieldValueIterator value_it(dex_file, + &dex_cache, + &class_loader, + this, + *dex_class_def); const uint8_t* class_data = dex_file.GetClassData(*dex_class_def); ClassDataItemIterator field_it(dex_file, class_data); if (value_it.HasNext()) { diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 9f3c2aa89..f8a11e5cc 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -28,6 +28,7 @@ #include "class_linker.h" #include "class_linker-inl.h" #include "dex_file-inl.h" +#include "dex_file_annotations.h" #include "dex_instruction.h" #include "entrypoints/runtime_asm_entrypoints.h" #include "gc/accounting/card_table-inl.h" @@ -3694,8 +3695,8 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache(); method = m; if (dex_cache != nullptr) { - const DexFile& dex_file = *dex_cache->GetDexFile(); - line_number = dex_file.GetLineNumFromPC(m, GetDexPc()); + const DexFile* dex_file = dex_cache->GetDexFile(); + line_number = annotations::GetLineNumFromPC(dex_file, m, GetDexPc()); } } } diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index 76cd348d8..ccc4c168e 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -27,28 +27,20 @@ #include #include -#include "art_field-inl.h" -#include "art_method-inl.h" #include "base/enums.h" #include "base/file_magic.h" #include "base/hash_map.h" #include "base/logging.h" #include "base/stl_util.h" -#include "base/stringprintf.h" #include "base/systrace.h" #include "base/unix_file/fd_file.h" #include "class_linker-inl.h" #include "dex_file-inl.h" #include "dex_file_verifier.h" #include "globals.h" -#include "handle_scope-inl.h" #include "jvalue.h" #include "leb128.h" -#include "mirror/field.h" -#include "mirror/method.h" -#include "mirror/string.h" #include "os.h" -#include "reflection.h" #include "safe_map.h" #include "thread.h" #include "type_lookup_table.h" @@ -864,22 +856,6 @@ const Signature DexFile::CreateSignature(const StringPiece& signature) const { return Signature(this, *proto_id); } -int32_t DexFile::GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const { - // For native method, lineno should be -2 to indicate it is native. Note that - // "line number == -2" is how libcore tells from StackTraceElement. - if (method->GetCodeItemOffset() == 0) { - return -2; - } - - const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset()); - DCHECK(code_item != nullptr) << PrettyMethod(method) << " " << GetLocation(); - - // A method with no line number info should return -1 - LineNumFromPcContext context(rel_pc, -1); - DecodeDebugPositionInfo(code_item, LineNumForPcCb, &context); - return context.line_num_; -} - int32_t DexFile::FindTryItem(const CodeItem &code_item, uint32_t address) { // Note: Signed type is important for max and min. int32_t min = 0; @@ -1186,7 +1162,7 @@ std::string DexFile::GetDexCanonicalLocation(const char* dex_location) { } // Read a signed integer. "zwidth" is the zero-based byte count. -static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth) { +int32_t DexFile::ReadSignedInt(const uint8_t* ptr, int zwidth) { int32_t val = 0; for (int i = zwidth; i >= 0; --i) { val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24); @@ -1197,7 +1173,7 @@ static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth) { // Read an unsigned integer. "zwidth" is the zero-based byte count, // "fill_on_right" indicates which side we want to zero-fill from. -static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) { +uint32_t DexFile::ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) { uint32_t val = 0; for (int i = zwidth; i >= 0; --i) { val = (val >> 8) | (((uint32_t)*ptr++) << 24); @@ -1209,7 +1185,7 @@ static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_rig } // Read a signed long. "zwidth" is the zero-based byte count. -static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth) { +int64_t DexFile::ReadSignedLong(const uint8_t* ptr, int zwidth) { int64_t val = 0; for (int i = zwidth; i >= 0; --i) { val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56); @@ -1220,7 +1196,7 @@ static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth) { // Read an unsigned long. "zwidth" is the zero-based byte count, // "fill_on_right" indicates which side we want to zero-fill from. -static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) { +uint64_t DexFile::ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) { uint64_t val = 0; for (int i = zwidth; i >= 0; --i) { val = (val >> 8) | (((uint64_t)*ptr++) << 56); @@ -1233,1150 +1209,6 @@ static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_ri // Checks that visibility is as expected. Includes special behavior for M and // before to allow runtime and build visibility when expecting runtime. -static bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) { - if (expected == DexFile::kDexVisibilityRuntime) { - int32_t sdk_version = Runtime::Current()->GetTargetSdkVersion(); - if (sdk_version > 0 && sdk_version <= 23) { - return actual == DexFile::kDexVisibilityRuntime || actual == DexFile::kDexVisibilityBuild; - } - } - return actual == expected; -} - -const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForField(ArtField* field) const { - mirror::Class* klass = field->GetDeclaringClass(); - const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); - if (annotations_dir == nullptr) { - return nullptr; - } - const FieldAnnotationsItem* field_annotations = GetFieldAnnotations(annotations_dir); - if (field_annotations == nullptr) { - return nullptr; - } - uint32_t field_index = field->GetDexFieldIndex(); - uint32_t field_count = annotations_dir->fields_size_; - for (uint32_t i = 0; i < field_count; ++i) { - if (field_annotations[i].field_idx_ == field_index) { - return GetFieldAnnotationSetItem(field_annotations[i]); - } - } - return nullptr; -} - -mirror::Object* DexFile::GetAnnotationForField(ArtField* field, - Handle annotation_class) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); - if (annotation_set == nullptr) { - return nullptr; - } - StackHandleScope<1> hs(Thread::Current()); - Handle field_class(hs.NewHandle(field->GetDeclaringClass())); - return GetAnnotationObjectFromAnnotationSet( - field_class, annotation_set, kDexVisibilityRuntime, annotation_class); -} - -mirror::ObjectArray* DexFile::GetAnnotationsForField(ArtField* field) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); - StackHandleScope<1> hs(Thread::Current()); - Handle field_class(hs.NewHandle(field->GetDeclaringClass())); - return ProcessAnnotationSet(field_class, annotation_set, kDexVisibilityRuntime); -} - -mirror::ObjectArray* DexFile::GetSignatureAnnotationForField(ArtField* field) - const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); - if (annotation_set == nullptr) { - return nullptr; - } - StackHandleScope<1> hs(Thread::Current()); - Handle field_class(hs.NewHandle(field->GetDeclaringClass())); - return GetSignatureValue(field_class, annotation_set); -} - -bool DexFile::IsFieldAnnotationPresent(ArtField* field, Handle annotation_class) - const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); - if (annotation_set == nullptr) { - return false; - } - StackHandleScope<1> hs(Thread::Current()); - Handle field_class(hs.NewHandle(field->GetDeclaringClass())); - const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( - field_class, annotation_set, kDexVisibilityRuntime, annotation_class); - return annotation_item != nullptr; -} - -const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForMethod(ArtMethod* method) const { - mirror::Class* klass = method->GetDeclaringClass(); - const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); - if (annotations_dir == nullptr) { - return nullptr; - } - const MethodAnnotationsItem* method_annotations = GetMethodAnnotations(annotations_dir); - if (method_annotations == nullptr) { - return nullptr; - } - uint32_t method_index = method->GetDexMethodIndex(); - uint32_t method_count = annotations_dir->methods_size_; - for (uint32_t i = 0; i < method_count; ++i) { - if (method_annotations[i].method_idx_ == method_index) { - return GetMethodAnnotationSetItem(method_annotations[i]); - } - } - return nullptr; -} - -const DexFile::ParameterAnnotationsItem* DexFile::FindAnnotationsItemForMethod(ArtMethod* method) - const { - mirror::Class* klass = method->GetDeclaringClass(); - const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); - if (annotations_dir == nullptr) { - return nullptr; - } - const ParameterAnnotationsItem* parameter_annotations = GetParameterAnnotations(annotations_dir); - if (parameter_annotations == nullptr) { - return nullptr; - } - uint32_t method_index = method->GetDexMethodIndex(); - uint32_t parameter_count = annotations_dir->parameters_size_; - for (uint32_t i = 0; i < parameter_count; ++i) { - if (parameter_annotations[i].method_idx_ == method_index) { - return ¶meter_annotations[i]; - } - } - return nullptr; -} - -mirror::Object* DexFile::GetAnnotationDefaultValue(ArtMethod* method) const { - mirror::Class* klass = method->GetDeclaringClass(); - const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); - if (annotations_dir == nullptr) { - return nullptr; - } - const AnnotationSetItem* annotation_set = GetClassAnnotationSet(annotations_dir); - if (annotation_set == nullptr) { - return nullptr; - } - const AnnotationItem* annotation_item = SearchAnnotationSet(annotation_set, - "Ldalvik/annotation/AnnotationDefault;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return nullptr; - } - const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "value"); - if (annotation == nullptr) { - return nullptr; - } - uint8_t header_byte = *(annotation++); - if ((header_byte & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) { - return nullptr; - } - annotation = SearchEncodedAnnotation(annotation, method->GetName()); - if (annotation == nullptr) { - return nullptr; - } - AnnotationValue annotation_value; - StackHandleScope<2> hs(Thread::Current()); - Handle h_klass(hs.NewHandle(klass)); - PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); - Handle return_type(hs.NewHandle( - method->GetReturnType(true /* resolve */, pointer_size))); - if (!ProcessAnnotationValue(h_klass, &annotation, &annotation_value, return_type, kAllObjects)) { - return nullptr; - } - return annotation_value.value_.GetL(); -} - -mirror::Object* DexFile::GetAnnotationForMethod(ArtMethod* method, - Handle annotation_class) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); - if (annotation_set == nullptr) { - return nullptr; - } - StackHandleScope<1> hs(Thread::Current()); - Handle method_class(hs.NewHandle(method->GetDeclaringClass())); - return GetAnnotationObjectFromAnnotationSet(method_class, annotation_set, - kDexVisibilityRuntime, annotation_class); -} - -mirror::ObjectArray* DexFile::GetAnnotationsForMethod(ArtMethod* method) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); - StackHandleScope<1> hs(Thread::Current()); - Handle method_class(hs.NewHandle(method->GetDeclaringClass())); - return ProcessAnnotationSet(method_class, annotation_set, kDexVisibilityRuntime); -} - -mirror::ObjectArray* DexFile::GetExceptionTypesForMethod(ArtMethod* method) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); - if (annotation_set == nullptr) { - return nullptr; - } - StackHandleScope<1> hs(Thread::Current()); - Handle method_class(hs.NewHandle(method->GetDeclaringClass())); - return GetThrowsValue(method_class, annotation_set); -} - -mirror::ObjectArray* DexFile::GetParameterAnnotations(ArtMethod* method) const { - const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method); - if (parameter_annotations == nullptr) { - return nullptr; - } - const AnnotationSetRefList* set_ref_list = - GetParameterAnnotationSetRefList(parameter_annotations); - if (set_ref_list == nullptr) { - return nullptr; - } - uint32_t size = set_ref_list->size_; - StackHandleScope<1> hs(Thread::Current()); - Handle method_class(hs.NewHandle(method->GetDeclaringClass())); - return ProcessAnnotationSetRefList(method_class, set_ref_list, size); -} - -mirror::Object* DexFile::GetAnnotationForMethodParameter(ArtMethod* method, - uint32_t parameter_idx, - Handle annotation_class) - const { - const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method); - if (parameter_annotations == nullptr) { - return nullptr; - } - const AnnotationSetRefList* set_ref_list = - GetParameterAnnotationSetRefList(parameter_annotations); - if (set_ref_list == nullptr) { - return nullptr; - } - - if (parameter_idx >= set_ref_list->size_) { - return nullptr; - } - const AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx]; - const AnnotationSetItem* annotation_set = GetSetRefItemItem(annotation_set_ref); - - StackHandleScope<1> hs(Thread::Current()); - Handle method_class(hs.NewHandle(method->GetDeclaringClass())); - return GetAnnotationObjectFromAnnotationSet(method_class, - annotation_set, - kDexVisibilityRuntime, - annotation_class); -} - -mirror::ObjectArray* DexFile::GetSignatureAnnotationForMethod(ArtMethod* method) - const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); - if (annotation_set == nullptr) { - return nullptr; - } - StackHandleScope<1> hs(Thread::Current()); - Handle method_class(hs.NewHandle(method->GetDeclaringClass())); - return GetSignatureValue(method_class, annotation_set); -} - -bool DexFile::IsMethodAnnotationPresent(ArtMethod* method, - Handle annotation_class, - uint32_t visibility /* = kDexVisibilityRuntime */) - const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); - if (annotation_set == nullptr) { - return false; - } - StackHandleScope<1> hs(Thread::Current()); - Handle method_class(hs.NewHandle(method->GetDeclaringClass())); - const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(method_class, - annotation_set, - visibility, - annotation_class); - return annotation_item != nullptr; -} - -const DexFile::AnnotationSetItem* DexFile::FindAnnotationSetForClass(Handle klass) - const { - const AnnotationsDirectoryItem* annotations_dir = GetAnnotationsDirectory(*klass->GetClassDef()); - if (annotations_dir == nullptr) { - return nullptr; - } - return GetClassAnnotationSet(annotations_dir); -} - -mirror::Object* DexFile::GetAnnotationForClass(Handle klass, - Handle annotation_class) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return nullptr; - } - return GetAnnotationObjectFromAnnotationSet(klass, annotation_set, kDexVisibilityRuntime, - annotation_class); -} - -mirror::ObjectArray* DexFile::GetAnnotationsForClass(Handle klass) - const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - return ProcessAnnotationSet(klass, annotation_set, kDexVisibilityRuntime); -} - -mirror::ObjectArray* DexFile::GetDeclaredClasses(Handle klass) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return nullptr; - } - const AnnotationItem* annotation_item = SearchAnnotationSet( - annotation_set, "Ldalvik/annotation/MemberClasses;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return nullptr; - } - StackHandleScope<1> hs(Thread::Current()); - mirror::Class* class_class = mirror::Class::GetJavaLangClass(); - Handle class_array_class(hs.NewHandle( - Runtime::Current()->GetClassLinker()->FindArrayClass(hs.Self(), &class_class))); - if (class_array_class.Get() == nullptr) { - return nullptr; - } - mirror::Object* obj = GetAnnotationValue( - klass, annotation_item, "value", class_array_class, kDexAnnotationArray); - if (obj == nullptr) { - return nullptr; - } - return obj->AsObjectArray(); -} - -mirror::Class* DexFile::GetDeclaringClass(Handle klass) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return nullptr; - } - const AnnotationItem* annotation_item = SearchAnnotationSet( - annotation_set, "Ldalvik/annotation/EnclosingClass;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return nullptr; - } - mirror::Object* obj = GetAnnotationValue(klass, - annotation_item, - "value", - ScopedNullHandle(), - kDexAnnotationType); - if (obj == nullptr) { - return nullptr; - } - return obj->AsClass(); -} - -mirror::Class* DexFile::GetEnclosingClass(Handle klass) const { - mirror::Class* declaring_class = GetDeclaringClass(klass); - if (declaring_class != nullptr) { - return declaring_class; - } - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return nullptr; - } - const AnnotationItem* annotation_item = SearchAnnotationSet( - annotation_set, "Ldalvik/annotation/EnclosingMethod;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return nullptr; - } - const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "value"); - if (annotation == nullptr) { - return nullptr; - } - AnnotationValue annotation_value; - if (!ProcessAnnotationValue(klass, - &annotation, - &annotation_value, - ScopedNullHandle(), - kAllRaw)) { - return nullptr; - } - if (annotation_value.type_ != kDexAnnotationMethod) { - return nullptr; - } - StackHandleScope<2> hs(Thread::Current()); - Handle dex_cache(hs.NewHandle(klass->GetDexCache())); - Handle class_loader(hs.NewHandle(klass->GetClassLoader())); - ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType( - klass->GetDexFile(), annotation_value.value_.GetI(), dex_cache, class_loader); - if (method == nullptr) { - return nullptr; - } - return method->GetDeclaringClass(); -} - -mirror::Object* DexFile::GetEnclosingMethod(Handle klass) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return nullptr; - } - const AnnotationItem* annotation_item = SearchAnnotationSet( - annotation_set, "Ldalvik/annotation/EnclosingMethod;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return nullptr; - } - return GetAnnotationValue( - klass, annotation_item, "value", ScopedNullHandle(), kDexAnnotationMethod); -} - -bool DexFile::GetInnerClass(Handle klass, mirror::String** name) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return false; - } - const AnnotationItem* annotation_item = SearchAnnotationSet( - annotation_set, "Ldalvik/annotation/InnerClass;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return false; - } - const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "name"); - if (annotation == nullptr) { - return false; - } - AnnotationValue annotation_value; - if (!ProcessAnnotationValue(klass, - &annotation, - &annotation_value, - ScopedNullHandle(), - kAllObjects)) { - return false; - } - if (annotation_value.type_ != kDexAnnotationNull && - annotation_value.type_ != kDexAnnotationString) { - return false; - } - *name = down_cast(annotation_value.value_.GetL()); - return true; -} - -bool DexFile::GetInnerClassFlags(Handle klass, uint32_t* flags) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return false; - } - const AnnotationItem* annotation_item = SearchAnnotationSet( - annotation_set, "Ldalvik/annotation/InnerClass;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return false; - } - const uint8_t* annotation = SearchEncodedAnnotation(annotation_item->annotation_, "accessFlags"); - if (annotation == nullptr) { - return false; - } - AnnotationValue annotation_value; - if (!ProcessAnnotationValue(klass, - &annotation, - &annotation_value, - ScopedNullHandle(), - kAllRaw)) { - return false; - } - if (annotation_value.type_ != kDexAnnotationInt) { - return false; - } - *flags = annotation_value.value_.GetI(); - return true; -} - -mirror::ObjectArray* DexFile::GetSignatureAnnotationForClass( - Handle klass) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return nullptr; - } - return GetSignatureValue(klass, annotation_set); -} - -bool DexFile::IsClassAnnotationPresent(Handle klass, - Handle annotation_class) const { - const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); - if (annotation_set == nullptr) { - return false; - } - const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( - klass, annotation_set, kDexVisibilityRuntime, annotation_class); - return annotation_item != nullptr; -} - -mirror::Object* DexFile::CreateAnnotationMember(Handle klass, - Handle annotation_class, const uint8_t** annotation) const { - Thread* self = Thread::Current(); - ScopedObjectAccessUnchecked soa(self); - StackHandleScope<5> hs(self); - uint32_t element_name_index = DecodeUnsignedLeb128(annotation); - const char* name = StringDataByIdx(element_name_index); - Handle string_name( - hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name))); - - PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); - ArtMethod* annotation_method = - annotation_class->FindDeclaredVirtualMethodByName(name, pointer_size); - if (annotation_method == nullptr) { - return nullptr; - } - Handle method_return(hs.NewHandle( - annotation_method->GetReturnType(true /* resolve */, pointer_size))); - - AnnotationValue annotation_value; - if (!ProcessAnnotationValue(klass, annotation, &annotation_value, method_return, kAllObjects)) { - return nullptr; - } - Handle value_object(hs.NewHandle(annotation_value.value_.GetL())); - - mirror::Class* annotation_member_class = - WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember); - Handle new_member(hs.NewHandle(annotation_member_class->AllocObject(self))); - mirror::Method* method_obj_ptr; - DCHECK(!Runtime::Current()->IsActiveTransaction()); - if (pointer_size == PointerSize::k64) { - method_obj_ptr = mirror::Method::CreateFromArtMethod( - self, annotation_method); - } else { - method_obj_ptr = mirror::Method::CreateFromArtMethod( - self, annotation_method); - } - Handle method_object(hs.NewHandle(method_obj_ptr)); - - if (new_member.Get() == nullptr || string_name.Get() == nullptr || - method_object.Get() == nullptr || method_return.Get() == nullptr) { - LOG(ERROR) << StringPrintf("Failed creating annotation element (m=%p n=%p a=%p r=%p", - new_member.Get(), string_name.Get(), method_object.Get(), method_return.Get()); - return nullptr; - } - - JValue result; - ArtMethod* annotation_member_init = - soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationMember_init); - uint32_t args[5] = { static_cast(reinterpret_cast(new_member.Get())), - static_cast(reinterpret_cast(string_name.Get())), - static_cast(reinterpret_cast(value_object.Get())), - static_cast(reinterpret_cast(method_return.Get())), - static_cast(reinterpret_cast(method_object.Get())) - }; - annotation_member_init->Invoke(self, args, sizeof(args), &result, "VLLLL"); - if (self->IsExceptionPending()) { - LOG(INFO) << "Exception in AnnotationMember."; - return nullptr; - } - - return new_member.Get(); -} - -const DexFile::AnnotationItem* DexFile::GetAnnotationItemFromAnnotationSet( - Handle klass, const AnnotationSetItem* annotation_set, uint32_t visibility, - Handle annotation_class) const { - for (uint32_t i = 0; i < annotation_set->size_; ++i) { - const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i); - if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) { - continue; - } - const uint8_t* annotation = annotation_item->annotation_; - uint32_t type_index = DecodeUnsignedLeb128(&annotation); - mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->ResolveType( - klass->GetDexFile(), type_index, klass.Get()); - if (resolved_class == nullptr) { - std::string temp; - LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d", - klass->GetDescriptor(&temp), type_index); - CHECK(Thread::Current()->IsExceptionPending()); - Thread::Current()->ClearException(); - continue; - } - if (resolved_class == annotation_class.Get()) { - return annotation_item; - } - } - - return nullptr; -} - -mirror::Object* DexFile::GetAnnotationObjectFromAnnotationSet(Handle klass, - const AnnotationSetItem* annotation_set, uint32_t visibility, - Handle annotation_class) const { - const AnnotationItem* annotation_item = - GetAnnotationItemFromAnnotationSet(klass, annotation_set, visibility, annotation_class); - if (annotation_item == nullptr) { - return nullptr; - } - const uint8_t* annotation = annotation_item->annotation_; - return ProcessEncodedAnnotation(klass, &annotation); -} - -mirror::Object* DexFile::GetAnnotationValue(Handle klass, - const AnnotationItem* annotation_item, const char* annotation_name, - Handle array_class, uint32_t expected_type) const { - const uint8_t* annotation = - SearchEncodedAnnotation(annotation_item->annotation_, annotation_name); - if (annotation == nullptr) { - return nullptr; - } - AnnotationValue annotation_value; - if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, array_class, kAllObjects)) { - return nullptr; - } - if (annotation_value.type_ != expected_type) { - return nullptr; - } - return annotation_value.value_.GetL(); -} - -mirror::ObjectArray* DexFile::GetSignatureValue(Handle klass, - const AnnotationSetItem* annotation_set) const { - StackHandleScope<1> hs(Thread::Current()); - const AnnotationItem* annotation_item = - SearchAnnotationSet(annotation_set, "Ldalvik/annotation/Signature;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return nullptr; - } - mirror::Class* string_class = mirror::String::GetJavaLangString(); - Handle string_array_class(hs.NewHandle( - Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class))); - if (string_array_class.Get() == nullptr) { - return nullptr; - } - mirror::Object* obj = - GetAnnotationValue(klass, annotation_item, "value", string_array_class, kDexAnnotationArray); - if (obj == nullptr) { - return nullptr; - } - return obj->AsObjectArray(); -} - -mirror::ObjectArray* DexFile::GetThrowsValue(Handle klass, - const AnnotationSetItem* annotation_set) const { - StackHandleScope<1> hs(Thread::Current()); - const AnnotationItem* annotation_item = - SearchAnnotationSet(annotation_set, "Ldalvik/annotation/Throws;", kDexVisibilitySystem); - if (annotation_item == nullptr) { - return nullptr; - } - mirror::Class* class_class = mirror::Class::GetJavaLangClass(); - Handle class_array_class(hs.NewHandle( - Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &class_class))); - if (class_array_class.Get() == nullptr) { - return nullptr; - } - mirror::Object* obj = - GetAnnotationValue(klass, annotation_item, "value", class_array_class, kDexAnnotationArray); - if (obj == nullptr) { - return nullptr; - } - return obj->AsObjectArray(); -} - -mirror::ObjectArray* DexFile::ProcessAnnotationSet(Handle klass, - const AnnotationSetItem* annotation_set, uint32_t visibility) const { - Thread* self = Thread::Current(); - ScopedObjectAccessUnchecked soa(self); - StackHandleScope<2> hs(self); - Handle annotation_array_class(hs.NewHandle( - soa.Decode(WellKnownClasses::java_lang_annotation_Annotation__array))); - if (annotation_set == nullptr) { - return mirror::ObjectArray::Alloc(self, annotation_array_class.Get(), 0); - } - - uint32_t size = annotation_set->size_; - Handle> result(hs.NewHandle( - mirror::ObjectArray::Alloc(self, annotation_array_class.Get(), size))); - if (result.Get() == nullptr) { - return nullptr; - } - - uint32_t dest_index = 0; - for (uint32_t i = 0; i < size; ++i) { - const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i); - // Note that we do not use IsVisibilityCompatible here because older code - // was correct for this case. - if (annotation_item->visibility_ != visibility) { - continue; - } - const uint8_t* annotation = annotation_item->annotation_; - mirror::Object* annotation_obj = ProcessEncodedAnnotation(klass, &annotation); - if (annotation_obj != nullptr) { - result->SetWithoutChecks(dest_index, annotation_obj); - ++dest_index; - } else if (self->IsExceptionPending()) { - return nullptr; - } - } - - if (dest_index == size) { - return result.Get(); - } - - mirror::ObjectArray* trimmed_result = - mirror::ObjectArray::Alloc(self, annotation_array_class.Get(), dest_index); - if (trimmed_result == nullptr) { - return nullptr; - } - - for (uint32_t i = 0; i < dest_index; ++i) { - mirror::Object* obj = result->GetWithoutChecks(i); - trimmed_result->SetWithoutChecks(i, obj); - } - - return trimmed_result; -} - -mirror::ObjectArray* DexFile::ProcessAnnotationSetRefList( - Handle klass, const AnnotationSetRefList* set_ref_list, uint32_t size) const { - Thread* self = Thread::Current(); - ScopedObjectAccessUnchecked soa(self); - StackHandleScope<1> hs(self); - mirror::Class* annotation_array_class = - soa.Decode(WellKnownClasses::java_lang_annotation_Annotation__array); - mirror::Class* annotation_array_array_class = - Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class); - if (annotation_array_array_class == nullptr) { - return nullptr; - } - Handle> annotation_array_array(hs.NewHandle( - mirror::ObjectArray::Alloc(self, annotation_array_array_class, size))); - if (annotation_array_array.Get() == nullptr) { - LOG(ERROR) << "Annotation set ref array allocation failed"; - return nullptr; - } - for (uint32_t index = 0; index < size; ++index) { - const AnnotationSetRefItem* set_ref_item = &set_ref_list->list_[index]; - const AnnotationSetItem* set_item = GetSetRefItemItem(set_ref_item); - mirror::Object* annotation_set = ProcessAnnotationSet(klass, set_item, kDexVisibilityRuntime); - if (annotation_set == nullptr) { - return nullptr; - } - annotation_array_array->SetWithoutChecks(index, annotation_set); - } - return annotation_array_array.Get(); -} - -bool DexFile::ProcessAnnotationValue(Handle klass, const uint8_t** annotation_ptr, - AnnotationValue* annotation_value, Handle array_class, - DexFile::AnnotationResultStyle result_style) const { - Thread* self = Thread::Current(); - mirror::Object* element_object = nullptr; - bool set_object = false; - Primitive::Type primitive_type = Primitive::kPrimVoid; - const uint8_t* annotation = *annotation_ptr; - uint8_t header_byte = *(annotation++); - uint8_t value_type = header_byte & kDexAnnotationValueTypeMask; - uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift; - int32_t width = value_arg + 1; - annotation_value->type_ = value_type; - - switch (value_type) { - case kDexAnnotationByte: - annotation_value->value_.SetB(static_cast(ReadSignedInt(annotation, value_arg))); - primitive_type = Primitive::kPrimByte; - break; - case kDexAnnotationShort: - annotation_value->value_.SetS(static_cast(ReadSignedInt(annotation, value_arg))); - primitive_type = Primitive::kPrimShort; - break; - case kDexAnnotationChar: - annotation_value->value_.SetC(static_cast(ReadUnsignedInt(annotation, value_arg, - false))); - primitive_type = Primitive::kPrimChar; - break; - case kDexAnnotationInt: - annotation_value->value_.SetI(ReadSignedInt(annotation, value_arg)); - primitive_type = Primitive::kPrimInt; - break; - case kDexAnnotationLong: - annotation_value->value_.SetJ(ReadSignedLong(annotation, value_arg)); - primitive_type = Primitive::kPrimLong; - break; - case kDexAnnotationFloat: - annotation_value->value_.SetI(ReadUnsignedInt(annotation, value_arg, true)); - primitive_type = Primitive::kPrimFloat; - break; - case kDexAnnotationDouble: - annotation_value->value_.SetJ(ReadUnsignedLong(annotation, value_arg, true)); - primitive_type = Primitive::kPrimDouble; - break; - case kDexAnnotationBoolean: - annotation_value->value_.SetZ(value_arg != 0); - primitive_type = Primitive::kPrimBoolean; - width = 0; - break; - case kDexAnnotationString: { - uint32_t index = ReadUnsignedInt(annotation, value_arg, false); - if (result_style == kAllRaw) { - annotation_value->value_.SetI(index); - } else { - StackHandleScope<1> hs(self); - Handle dex_cache(hs.NewHandle(klass->GetDexCache())); - element_object = Runtime::Current()->GetClassLinker()->ResolveString( - klass->GetDexFile(), index, dex_cache); - set_object = true; - if (element_object == nullptr) { - return false; - } - } - break; - } - case kDexAnnotationType: { - uint32_t index = ReadUnsignedInt(annotation, value_arg, false); - if (result_style == kAllRaw) { - annotation_value->value_.SetI(index); - } else { - element_object = Runtime::Current()->GetClassLinker()->ResolveType( - klass->GetDexFile(), index, klass.Get()); - set_object = true; - if (element_object == nullptr) { - CHECK(self->IsExceptionPending()); - if (result_style == kAllObjects) { - const char* msg = StringByTypeIdx(index); - self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg); - element_object = self->GetException(); - self->ClearException(); - } else { - return false; - } - } - } - break; - } - case kDexAnnotationMethod: { - uint32_t index = ReadUnsignedInt(annotation, value_arg, false); - if (result_style == kAllRaw) { - annotation_value->value_.SetI(index); - } else { - StackHandleScope<2> hs(self); - Handle dex_cache(hs.NewHandle(klass->GetDexCache())); - Handle class_loader(hs.NewHandle(klass->GetClassLoader())); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType( - klass->GetDexFile(), index, dex_cache, class_loader); - if (method == nullptr) { - return false; - } - PointerSize pointer_size = class_linker->GetImagePointerSize(); - set_object = true; - DCHECK(!Runtime::Current()->IsActiveTransaction()); - if (method->IsConstructor()) { - if (pointer_size == PointerSize::k64) { - element_object = mirror::Constructor::CreateFromArtMethod(self, method); - } else { - element_object = mirror::Constructor::CreateFromArtMethod(self, method); - } - } else { - if (pointer_size == PointerSize::k64) { - element_object = mirror::Method::CreateFromArtMethod(self, method); - } else { - element_object = mirror::Method::CreateFromArtMethod(self, method); - } - } - if (element_object == nullptr) { - return false; - } - } - break; - } - case kDexAnnotationField: { - uint32_t index = ReadUnsignedInt(annotation, value_arg, false); - if (result_style == kAllRaw) { - annotation_value->value_.SetI(index); - } else { - StackHandleScope<2> hs(self); - Handle dex_cache(hs.NewHandle(klass->GetDexCache())); - Handle class_loader(hs.NewHandle(klass->GetClassLoader())); - ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS( - klass->GetDexFile(), index, dex_cache, class_loader); - if (field == nullptr) { - return false; - } - set_object = true; - PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); - if (pointer_size == PointerSize::k64) { - element_object = mirror::Field::CreateFromArtField(self, field, true); - } else { - element_object = mirror::Field::CreateFromArtField(self, field, true); - } - if (element_object == nullptr) { - return false; - } - } - break; - } - case kDexAnnotationEnum: { - uint32_t index = ReadUnsignedInt(annotation, value_arg, false); - if (result_style == kAllRaw) { - annotation_value->value_.SetI(index); - } else { - StackHandleScope<3> hs(self); - Handle dex_cache(hs.NewHandle(klass->GetDexCache())); - Handle class_loader(hs.NewHandle(klass->GetClassLoader())); - ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField( - klass->GetDexFile(), index, dex_cache, class_loader, true); - if (enum_field == nullptr) { - return false; - } else { - Handle field_class(hs.NewHandle(enum_field->GetDeclaringClass())); - Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, true, true); - element_object = enum_field->GetObject(field_class.Get()); - set_object = true; - } - } - break; - } - case kDexAnnotationArray: - if (result_style == kAllRaw || array_class.Get() == nullptr) { - return false; - } else { - ScopedObjectAccessUnchecked soa(self); - StackHandleScope<2> hs(self); - uint32_t size = DecodeUnsignedLeb128(&annotation); - Handle component_type(hs.NewHandle(array_class->GetComponentType())); - Handle new_array(hs.NewHandle(mirror::Array::Alloc( - self, array_class.Get(), size, array_class->GetComponentSizeShift(), - Runtime::Current()->GetHeap()->GetCurrentAllocator()))); - if (new_array.Get() == nullptr) { - LOG(ERROR) << "Annotation element array allocation failed with size " << size; - return false; - } - AnnotationValue new_annotation_value; - for (uint32_t i = 0; i < size; ++i) { - if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value, component_type, - kPrimitivesOrObjects)) { - return false; - } - if (!component_type->IsPrimitive()) { - mirror::Object* obj = new_annotation_value.value_.GetL(); - new_array->AsObjectArray()->SetWithoutChecks(i, obj); - } else { - switch (new_annotation_value.type_) { - case kDexAnnotationByte: - new_array->AsByteArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetB()); - break; - case kDexAnnotationShort: - new_array->AsShortArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetS()); - break; - case kDexAnnotationChar: - new_array->AsCharArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetC()); - break; - case kDexAnnotationInt: - new_array->AsIntArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetI()); - break; - case kDexAnnotationLong: - new_array->AsLongArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetJ()); - break; - case kDexAnnotationFloat: - new_array->AsFloatArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetF()); - break; - case kDexAnnotationDouble: - new_array->AsDoubleArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetD()); - break; - case kDexAnnotationBoolean: - new_array->AsBooleanArray()->SetWithoutChecks( - i, new_annotation_value.value_.GetZ()); - break; - default: - LOG(FATAL) << "Found invalid annotation value type while building annotation array"; - return false; - } - } - } - element_object = new_array.Get(); - set_object = true; - width = 0; - } - break; - case kDexAnnotationAnnotation: - if (result_style == kAllRaw) { - return false; - } - element_object = ProcessEncodedAnnotation(klass, &annotation); - if (element_object == nullptr) { - return false; - } - set_object = true; - width = 0; - break; - case kDexAnnotationNull: - if (result_style == kAllRaw) { - annotation_value->value_.SetI(0); - } else { - CHECK(element_object == nullptr); - set_object = true; - } - width = 0; - break; - default: - LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type); - return false; - } - - annotation += width; - *annotation_ptr = annotation; - - if (result_style == kAllObjects && primitive_type != Primitive::kPrimVoid) { - element_object = BoxPrimitive(primitive_type, annotation_value->value_); - set_object = true; - } - - if (set_object) { - annotation_value->value_.SetL(element_object); - } - - return true; -} - -mirror::Object* DexFile::ProcessEncodedAnnotation(Handle klass, - const uint8_t** annotation) const { - uint32_t type_index = DecodeUnsignedLeb128(annotation); - uint32_t size = DecodeUnsignedLeb128(annotation); - - Thread* self = Thread::Current(); - ScopedObjectAccessUnchecked soa(self); - StackHandleScope<2> hs(self); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Handle annotation_class(hs.NewHandle( - class_linker->ResolveType(klass->GetDexFile(), type_index, klass.Get()))); - if (annotation_class.Get() == nullptr) { - LOG(INFO) << "Unable to resolve " << PrettyClass(klass.Get()) << " annotation class " - << type_index; - DCHECK(Thread::Current()->IsExceptionPending()); - Thread::Current()->ClearException(); - return nullptr; - } - - mirror::Class* annotation_member_class = - soa.Decode(WellKnownClasses::libcore_reflect_AnnotationMember); - mirror::Class* annotation_member_array_class = - class_linker->FindArrayClass(self, &annotation_member_class); - if (annotation_member_array_class == nullptr) { - return nullptr; - } - mirror::ObjectArray* element_array = nullptr; - if (size > 0) { - element_array = - mirror::ObjectArray::Alloc(self, annotation_member_array_class, size); - if (element_array == nullptr) { - LOG(ERROR) << "Failed to allocate annotation member array (" << size << " elements)"; - return nullptr; - } - } - - Handle> h_element_array(hs.NewHandle(element_array)); - for (uint32_t i = 0; i < size; ++i) { - mirror::Object* new_member = CreateAnnotationMember(klass, annotation_class, annotation); - if (new_member == nullptr) { - return nullptr; - } - h_element_array->SetWithoutChecks(i, new_member); - } - - JValue result; - ArtMethod* create_annotation_method = - soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation); - uint32_t args[2] = { static_cast(reinterpret_cast(annotation_class.Get())), - static_cast(reinterpret_cast(h_element_array.Get())) }; - create_annotation_method->Invoke(self, args, sizeof(args), &result, "LLL"); - if (self->IsExceptionPending()) { - LOG(INFO) << "Exception in AnnotationFactory.createAnnotation"; - return nullptr; - } - - return result.GetL(); -} - -const DexFile::AnnotationItem* DexFile::SearchAnnotationSet(const AnnotationSetItem* annotation_set, - const char* descriptor, uint32_t visibility) const { - const AnnotationItem* result = nullptr; - for (uint32_t i = 0; i < annotation_set->size_; ++i) { - const AnnotationItem* annotation_item = GetAnnotationItem(annotation_set, i); - if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) { - continue; - } - const uint8_t* annotation = annotation_item->annotation_; - uint32_t type_index = DecodeUnsignedLeb128(&annotation); - - if (strcmp(descriptor, StringByTypeIdx(type_index)) == 0) { - result = annotation_item; - break; - } - } - return result; -} - -const uint8_t* DexFile::SearchEncodedAnnotation(const uint8_t* annotation, const char* name) const { - DecodeUnsignedLeb128(&annotation); // unused type_index - uint32_t size = DecodeUnsignedLeb128(&annotation); - - while (size != 0) { - uint32_t element_name_index = DecodeUnsignedLeb128(&annotation); - const char* element_name = GetStringData(GetStringId(element_name_index)); - if (strcmp(name, element_name) == 0) { - return annotation; - } - SkipAnnotationValue(&annotation); - size--; - } - return nullptr; -} - -bool DexFile::SkipAnnotationValue(const uint8_t** annotation_ptr) const { - const uint8_t* annotation = *annotation_ptr; - uint8_t header_byte = *(annotation++); - uint8_t value_type = header_byte & kDexAnnotationValueTypeMask; - uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift; - int32_t width = value_arg + 1; - - switch (value_type) { - case kDexAnnotationByte: - case kDexAnnotationShort: - case kDexAnnotationChar: - case kDexAnnotationInt: - case kDexAnnotationLong: - case kDexAnnotationFloat: - case kDexAnnotationDouble: - case kDexAnnotationString: - case kDexAnnotationType: - case kDexAnnotationMethod: - case kDexAnnotationField: - case kDexAnnotationEnum: - break; - case kDexAnnotationArray: - { - uint32_t size = DecodeUnsignedLeb128(&annotation); - while (size--) { - if (!SkipAnnotationValue(&annotation)) { - return false; - } - } - width = 0; - break; - } - case kDexAnnotationAnnotation: - { - DecodeUnsignedLeb128(&annotation); // unused type_index - uint32_t size = DecodeUnsignedLeb128(&annotation); - while (size--) { - DecodeUnsignedLeb128(&annotation); // unused element_name_index - if (!SkipAnnotationValue(&annotation)) { - return false; - } - } - width = 0; - break; - } - case kDexAnnotationBoolean: - case kDexAnnotationNull: - width = 0; - break; - default: - LOG(FATAL) << StringPrintf("Bad annotation element value byte 0x%02x", value_type); - return false; - } - - annotation += width; - *annotation_ptr = annotation; - return true; -} - std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) { os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]", dex_file.GetLocation().c_str(), @@ -2460,50 +1292,13 @@ void ClassDataItemIterator::ReadClassDataMethod() { } } -EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator( - const DexFile& dex_file, - const DexFile::ClassDef& class_def) - : EncodedStaticFieldValueIterator(dex_file, - nullptr, - nullptr, - nullptr, - class_def, - -1, - kByte) { -} - -EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator( - const DexFile& dex_file, - Handle* dex_cache, - Handle* class_loader, - ClassLinker* linker, - const DexFile::ClassDef& class_def) - : EncodedStaticFieldValueIterator(dex_file, - dex_cache, class_loader, - linker, - class_def, - -1, - kByte) { - DCHECK(dex_cache_ != nullptr); - DCHECK(class_loader_ != nullptr); -} - -EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator( - const DexFile& dex_file, - Handle* dex_cache, - Handle* class_loader, - ClassLinker* linker, - const DexFile::ClassDef& class_def, - size_t pos, - ValueType type) +EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file, + const DexFile::ClassDef& class_def) : dex_file_(dex_file), - dex_cache_(dex_cache), - class_loader_(class_loader), - linker_(linker), array_size_(), - pos_(pos), - type_(type) { - ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def); + pos_(-1), + type_(kByte) { + ptr_ = dex_file_.GetEncodedStaticFieldValuesArray(class_def); if (ptr_ == nullptr) { array_size_ = 0; } else { @@ -2529,32 +1324,32 @@ void EncodedStaticFieldValueIterator::Next() { width = 0; break; case kByte: - jval_.i = ReadSignedInt(ptr_, value_arg); + jval_.i = DexFile::ReadSignedInt(ptr_, value_arg); CHECK(IsInt<8>(jval_.i)); break; case kShort: - jval_.i = ReadSignedInt(ptr_, value_arg); + jval_.i = DexFile::ReadSignedInt(ptr_, value_arg); CHECK(IsInt<16>(jval_.i)); break; case kChar: - jval_.i = ReadUnsignedInt(ptr_, value_arg, false); + jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false); CHECK(IsUint<16>(jval_.i)); break; case kInt: - jval_.i = ReadSignedInt(ptr_, value_arg); + jval_.i = DexFile::ReadSignedInt(ptr_, value_arg); break; case kLong: - jval_.j = ReadSignedLong(ptr_, value_arg); + jval_.j = DexFile::ReadSignedLong(ptr_, value_arg); break; case kFloat: - jval_.i = ReadUnsignedInt(ptr_, value_arg, true); + jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, true); break; case kDouble: - jval_.j = ReadUnsignedLong(ptr_, value_arg, true); + jval_.j = DexFile::ReadUnsignedLong(ptr_, value_arg, true); break; case kString: case kType: - jval_.i = ReadUnsignedInt(ptr_, value_arg, false); + jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false); break; case kField: case kMethod: @@ -2574,38 +1369,6 @@ void EncodedStaticFieldValueIterator::Next() { ptr_ += width; } -template -void EncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const { - DCHECK(dex_cache_ != nullptr); - DCHECK(class_loader_ != nullptr); - switch (type_) { - case kBoolean: field->SetBoolean(field->GetDeclaringClass(), jval_.z); - break; - case kByte: field->SetByte(field->GetDeclaringClass(), jval_.b); break; - case kShort: field->SetShort(field->GetDeclaringClass(), jval_.s); break; - case kChar: field->SetChar(field->GetDeclaringClass(), jval_.c); break; - case kInt: field->SetInt(field->GetDeclaringClass(), jval_.i); break; - case kLong: field->SetLong(field->GetDeclaringClass(), jval_.j); break; - case kFloat: field->SetFloat(field->GetDeclaringClass(), jval_.f); break; - case kDouble: field->SetDouble(field->GetDeclaringClass(), jval_.d); break; - case kNull: field->SetObject(field->GetDeclaringClass(), nullptr); break; - case kString: { - mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_); - field->SetObject(field->GetDeclaringClass(), resolved); - break; - } - case kType: { - mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_, - *class_loader_); - field->SetObject(field->GetDeclaringClass(), resolved); - break; - } - default: UNIMPLEMENTED(FATAL) << ": type " << type_; - } -} -template void EncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const; -template void EncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const; - CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) { handler_.address_ = -1; int32_t offset = -1; diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 23676bdbf..0ae36f78b 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -27,27 +27,14 @@ #include "globals.h" #include "invoke_type.h" #include "jni.h" -#include "mirror/object_array.h" #include "modifiers.h" #include "utf.h" namespace art { -// TODO: remove dependencies on mirror classes, primarily by moving -// EncodedStaticFieldValueIterator to its own file. -namespace mirror { - class ClassLoader; - class DexCache; -} // namespace mirror -class ArtField; -class ArtMethod; -class ClassLinker; -template -class HashMap; class MemMap; class OatDexFile; class Signature; -template class Handle; class StringPiece; class TypeLookupTable; class ZipArchive; @@ -402,6 +389,8 @@ class DexFile { kAllRaw }; + struct AnnotationValue; + // Returns the checksum of a file for comparison with GetLocationChecksum(). // For .dex files, this is the header checksum. // For zip files, this is the classes.dex zip entry CRC32 checksum. @@ -934,110 +923,6 @@ class DexFile { return reinterpret_cast(begin_ + offset); } - const AnnotationSetItem* FindAnnotationSetForField(ArtField* field) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetAnnotationForField(ArtField* field, Handle annotation_class) - const REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetAnnotationsForField(ArtField* field) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetSignatureAnnotationForField(ArtField* field) const - REQUIRES_SHARED(Locks::mutator_lock_); - bool IsFieldAnnotationPresent(ArtField* field, Handle annotation_class) const - REQUIRES_SHARED(Locks::mutator_lock_); - - const AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method) const - REQUIRES_SHARED(Locks::mutator_lock_); - const ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle annotation_class) - const REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method, - uint32_t parameter_idx, - Handle annotation_class) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetAnnotationsForMethod(ArtMethod* method) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetExceptionTypesForMethod(ArtMethod* method) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetParameterAnnotations(ArtMethod* method) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetSignatureAnnotationForMethod(ArtMethod* method) const - REQUIRES_SHARED(Locks::mutator_lock_); - bool IsMethodAnnotationPresent(ArtMethod* method, - Handle annotation_class, - uint32_t visibility = kDexVisibilityRuntime) const - REQUIRES_SHARED(Locks::mutator_lock_); - - const AnnotationSetItem* FindAnnotationSetForClass(Handle klass) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetAnnotationForClass(Handle klass, - Handle annotation_class) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetAnnotationsForClass(Handle klass) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetDeclaredClasses(Handle klass) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Class* GetDeclaringClass(Handle klass) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Class* GetEnclosingClass(Handle klass) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetEnclosingMethod(Handle klass) const - REQUIRES_SHARED(Locks::mutator_lock_); - bool GetInnerClass(Handle klass, mirror::String** name) const - REQUIRES_SHARED(Locks::mutator_lock_); - bool GetInnerClassFlags(Handle klass, uint32_t* flags) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetSignatureAnnotationForClass(Handle klass) - const REQUIRES_SHARED(Locks::mutator_lock_); - bool IsClassAnnotationPresent(Handle klass, Handle annotation_class) - const REQUIRES_SHARED(Locks::mutator_lock_); - - mirror::Object* CreateAnnotationMember(Handle klass, - Handle annotation_class, - const uint8_t** annotation) const - REQUIRES_SHARED(Locks::mutator_lock_); - const AnnotationItem* GetAnnotationItemFromAnnotationSet(Handle klass, - const AnnotationSetItem* annotation_set, - uint32_t visibility, - Handle annotation_class) - const REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetAnnotationObjectFromAnnotationSet(Handle klass, - const AnnotationSetItem* annotation_set, - uint32_t visibility, - Handle annotation_class) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetAnnotationValue(Handle klass, - const AnnotationItem* annotation_item, - const char* annotation_name, - Handle array_class, - uint32_t expected_type) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetSignatureValue(Handle klass, - const AnnotationSetItem* annotation_set) - const REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* GetThrowsValue(Handle klass, - const AnnotationSetItem* annotation_set) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* ProcessAnnotationSet(Handle klass, - const AnnotationSetItem* annotation_set, - uint32_t visibility) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::ObjectArray* ProcessAnnotationSetRefList(Handle klass, - const AnnotationSetRefList* set_ref_list, uint32_t size) const - REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* ProcessEncodedAnnotation(Handle klass, - const uint8_t** annotation) const - REQUIRES_SHARED(Locks::mutator_lock_); - const AnnotationItem* SearchAnnotationSet(const AnnotationSetItem* annotation_set, - const char* descriptor, uint32_t visibility) const - REQUIRES_SHARED(Locks::mutator_lock_); - const uint8_t* SearchEncodedAnnotation(const uint8_t* annotation, const char* name) const - REQUIRES_SHARED(Locks::mutator_lock_); - bool SkipAnnotationValue(const uint8_t** annotation_ptr) const - REQUIRES_SHARED(Locks::mutator_lock_); - // Debug info opcodes and constants enum { DBG_END_SEQUENCE = 0x00, @@ -1064,17 +949,6 @@ class DexFile { DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext); }; - // Determine the source file line number based on the program counter. - // "pc" is an offset, in 16-bit units, from the start of the method's code. - // - // Returns -1 if no match was found (possibly because the source files were - // compiled without "-g", so no line number information is present). - // Returns -2 for native methods (as expected in exception traces). - // - // This is used by runtime; therefore use art::Method not art::DexFile::Method. - int32_t GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const - REQUIRES_SHARED(Locks::mutator_lock_); - // Returns false if there is no debugging information or if it cannot be decoded. bool DecodeDebugLocalInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx, DexDebugNewLocalCb local_cb, void* context) const; @@ -1140,6 +1014,12 @@ class DexFile { void CreateTypeLookupTable(uint8_t* storage = nullptr) const; + // Utility methods for reading integral values from a buffer. + static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth); + static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right); + static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth); + static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right); + private: // Opens a .dex file static std::unique_ptr OpenFile(int fd, @@ -1204,13 +1084,6 @@ class DexFile { // whether the string contains the separator character. static bool IsMultiDexLocation(const char* location); - struct AnnotationValue; - - bool ProcessAnnotationValue(Handle klass, const uint8_t** annotation_ptr, - AnnotationValue* annotation_value, Handle return_class, - DexFile::AnnotationResultStyle result_style) const - REQUIRES_SHARED(Locks::mutator_lock_); - // The base address of the memory mapping. const uint8_t* const begin_; @@ -1514,22 +1387,9 @@ class ClassDataItemIterator { class EncodedStaticFieldValueIterator { public: - // A constructor for static tools. You cannot call - // ReadValueToField() for an object created by this. EncodedStaticFieldValueIterator(const DexFile& dex_file, const DexFile::ClassDef& class_def); - // A constructor meant to be called from runtime code. - EncodedStaticFieldValueIterator(const DexFile& dex_file, - Handle* dex_cache, - Handle* class_loader, - ClassLinker* linker, - const DexFile::ClassDef& class_def) - REQUIRES_SHARED(Locks::mutator_lock_); - - template - void ReadValueToField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_); - bool HasNext() const { return pos_ < array_size_; } void Next(); @@ -1556,27 +1416,18 @@ class EncodedStaticFieldValueIterator { ValueType GetValueType() const { return type_; } const jvalue& GetJavaValue() const { return jval_; } - private: - EncodedStaticFieldValueIterator(const DexFile& dex_file, - Handle* dex_cache, - Handle* class_loader, - ClassLinker* linker, - const DexFile::ClassDef& class_def, - size_t pos, - ValueType type); - + protected: static constexpr uint8_t kEncodedValueTypeMask = 0x1f; // 0b11111 static constexpr uint8_t kEncodedValueArgShift = 5; const DexFile& dex_file_; - Handle* const dex_cache_; // Dex cache to resolve literal objects. - Handle* const class_loader_; // ClassLoader to resolve types. - ClassLinker* linker_; // Linker to resolve literal objects. size_t array_size_; // Size of array. size_t pos_; // Current position. const uint8_t* ptr_; // Pointer into encoded data array. ValueType type_; // Type of current encoded value. jvalue jval_; // Value of current encoded value. + + private: DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator); }; std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code); diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc new file mode 100644 index 000000000..c6c87fdf3 --- /dev/null +++ b/runtime/dex_file_annotations.cc @@ -0,0 +1,1303 @@ +/* + * Copyright (C) 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. + */ + +#include "dex_file_annotations.h" + +#include + +#include "art_field-inl.h" +#include "art_method-inl.h" +#include "class_linker-inl.h" +#include "dex_file-inl.h" +#include "jvalue.h" +#include "mirror/field.h" +#include "mirror/method.h" +#include "reflection.h" +#include "thread.h" + +namespace art { + +struct DexFile::AnnotationValue { + JValue value_; + uint8_t type_; +}; + +namespace { +mirror::Object* CreateAnnotationMember(Handle klass, + Handle annotation_class, + const uint8_t** annotation) + REQUIRES_SHARED(Locks::mutator_lock_); + +bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) { + if (expected == DexFile::kDexVisibilityRuntime) { + int32_t sdk_version = Runtime::Current()->GetTargetSdkVersion(); + if (sdk_version > 0 && sdk_version <= 23) { + return actual == DexFile::kDexVisibilityRuntime || actual == DexFile::kDexVisibilityBuild; + } + } + return actual == expected; +} + +const DexFile::AnnotationSetItem* FindAnnotationSetForField(ArtField* field) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile* dex_file = field->GetDexFile(); + mirror::Class* klass = field->GetDeclaringClass(); + const DexFile::AnnotationsDirectoryItem* annotations_dir = + dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const DexFile::FieldAnnotationsItem* field_annotations = + dex_file->GetFieldAnnotations(annotations_dir); + if (field_annotations == nullptr) { + return nullptr; + } + uint32_t field_index = field->GetDexFieldIndex(); + uint32_t field_count = annotations_dir->fields_size_; + for (uint32_t i = 0; i < field_count; ++i) { + if (field_annotations[i].field_idx_ == field_index) { + return dex_file->GetFieldAnnotationSetItem(field_annotations[i]); + } + } + return nullptr; +} + +const DexFile::AnnotationItem* SearchAnnotationSet(const DexFile& dex_file, + const DexFile::AnnotationSetItem* annotation_set, + const char* descriptor, + uint32_t visibility) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile::AnnotationItem* result = nullptr; + for (uint32_t i = 0; i < annotation_set->size_; ++i) { + const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i); + if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) { + continue; + } + const uint8_t* annotation = annotation_item->annotation_; + uint32_t type_index = DecodeUnsignedLeb128(&annotation); + + if (strcmp(descriptor, dex_file.StringByTypeIdx(type_index)) == 0) { + result = annotation_item; + break; + } + } + return result; +} + +bool SkipAnnotationValue(const DexFile& dex_file, const uint8_t** annotation_ptr) + REQUIRES_SHARED(Locks::mutator_lock_) { + const uint8_t* annotation = *annotation_ptr; + uint8_t header_byte = *(annotation++); + uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask; + uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift; + int32_t width = value_arg + 1; + + switch (value_type) { + case DexFile::kDexAnnotationByte: + case DexFile::kDexAnnotationShort: + case DexFile::kDexAnnotationChar: + case DexFile::kDexAnnotationInt: + case DexFile::kDexAnnotationLong: + case DexFile::kDexAnnotationFloat: + case DexFile::kDexAnnotationDouble: + case DexFile::kDexAnnotationString: + case DexFile::kDexAnnotationType: + case DexFile::kDexAnnotationMethod: + case DexFile::kDexAnnotationField: + case DexFile::kDexAnnotationEnum: + break; + case DexFile::kDexAnnotationArray: + { + uint32_t size = DecodeUnsignedLeb128(&annotation); + while (size--) { + if (!SkipAnnotationValue(dex_file, &annotation)) { + return false; + } + } + width = 0; + break; + } + case DexFile::kDexAnnotationAnnotation: + { + DecodeUnsignedLeb128(&annotation); // unused type_index + uint32_t size = DecodeUnsignedLeb128(&annotation); + while (size--) { + DecodeUnsignedLeb128(&annotation); // unused element_name_index + if (!SkipAnnotationValue(dex_file, &annotation)) { + return false; + } + } + width = 0; + break; + } + case DexFile::kDexAnnotationBoolean: + case DexFile::kDexAnnotationNull: + width = 0; + break; + default: + LOG(FATAL) << StringPrintf("Bad annotation element value byte 0x%02x", value_type); + return false; + } + + annotation += width; + *annotation_ptr = annotation; + return true; +} + +const uint8_t* SearchEncodedAnnotation(const DexFile& dex_file, + const uint8_t* annotation, + const char* name) + REQUIRES_SHARED(Locks::mutator_lock_) { + DecodeUnsignedLeb128(&annotation); // unused type_index + uint32_t size = DecodeUnsignedLeb128(&annotation); + + while (size != 0) { + uint32_t element_name_index = DecodeUnsignedLeb128(&annotation); + const char* element_name = dex_file.GetStringData(dex_file.GetStringId(element_name_index)); + if (strcmp(name, element_name) == 0) { + return annotation; + } + SkipAnnotationValue(dex_file, &annotation); + size--; + } + return nullptr; +} + +const DexFile::AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile* dex_file = method->GetDexFile(); + mirror::Class* klass = method->GetDeclaringClass(); + const DexFile::AnnotationsDirectoryItem* annotations_dir = + dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const DexFile::MethodAnnotationsItem* method_annotations = + dex_file->GetMethodAnnotations(annotations_dir); + if (method_annotations == nullptr) { + return nullptr; + } + uint32_t method_index = method->GetDexMethodIndex(); + uint32_t method_count = annotations_dir->methods_size_; + for (uint32_t i = 0; i < method_count; ++i) { + if (method_annotations[i].method_idx_ == method_index) { + return dex_file->GetMethodAnnotationSetItem(method_annotations[i]); + } + } + return nullptr; +} + +const DexFile::ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile* dex_file = method->GetDexFile(); + mirror::Class* klass = method->GetDeclaringClass(); + const DexFile::AnnotationsDirectoryItem* annotations_dir = + dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const DexFile::ParameterAnnotationsItem* parameter_annotations = + dex_file->GetParameterAnnotations(annotations_dir); + if (parameter_annotations == nullptr) { + return nullptr; + } + uint32_t method_index = method->GetDexMethodIndex(); + uint32_t parameter_count = annotations_dir->parameters_size_; + for (uint32_t i = 0; i < parameter_count; ++i) { + if (parameter_annotations[i].method_idx_ == method_index) { + return ¶meter_annotations[i]; + } + } + return nullptr; +} + +const DexFile::AnnotationSetItem* FindAnnotationSetForClass(Handle klass) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationsDirectoryItem* annotations_dir = + dex_file.GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + return dex_file.GetClassAnnotationSet(annotations_dir); +} + +mirror::Object* ProcessEncodedAnnotation(Handle klass, const uint8_t** annotation) + REQUIRES_SHARED(Locks::mutator_lock_) { + uint32_t type_index = DecodeUnsignedLeb128(annotation); + uint32_t size = DecodeUnsignedLeb128(annotation); + + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<2> hs(self); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + Handle annotation_class(hs.NewHandle( + class_linker->ResolveType(klass->GetDexFile(), type_index, klass.Get()))); + if (annotation_class.Get() == nullptr) { + LOG(INFO) << "Unable to resolve " << PrettyClass(klass.Get()) << " annotation class " + << type_index; + DCHECK(Thread::Current()->IsExceptionPending()); + Thread::Current()->ClearException(); + return nullptr; + } + + mirror::Class* annotation_member_class = + soa.Decode(WellKnownClasses::libcore_reflect_AnnotationMember); + mirror::Class* annotation_member_array_class = + class_linker->FindArrayClass(self, &annotation_member_class); + if (annotation_member_array_class == nullptr) { + return nullptr; + } + mirror::ObjectArray* element_array = nullptr; + if (size > 0) { + element_array = + mirror::ObjectArray::Alloc(self, annotation_member_array_class, size); + if (element_array == nullptr) { + LOG(ERROR) << "Failed to allocate annotation member array (" << size << " elements)"; + return nullptr; + } + } + + Handle> h_element_array(hs.NewHandle(element_array)); + for (uint32_t i = 0; i < size; ++i) { + mirror::Object* new_member = CreateAnnotationMember(klass, annotation_class, annotation); + if (new_member == nullptr) { + return nullptr; + } + h_element_array->SetWithoutChecks(i, new_member); + } + + JValue result; + ArtMethod* create_annotation_method = + soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation); + uint32_t args[2] = { static_cast(reinterpret_cast(annotation_class.Get())), + static_cast(reinterpret_cast(h_element_array.Get())) }; + create_annotation_method->Invoke(self, args, sizeof(args), &result, "LLL"); + if (self->IsExceptionPending()) { + LOG(INFO) << "Exception in AnnotationFactory.createAnnotation"; + return nullptr; + } + + return result.GetL(); +} + +bool ProcessAnnotationValue(Handle klass, + const uint8_t** annotation_ptr, + DexFile::AnnotationValue* annotation_value, + Handle array_class, + DexFile::AnnotationResultStyle result_style) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + Thread* self = Thread::Current(); + mirror::Object* element_object = nullptr; + bool set_object = false; + Primitive::Type primitive_type = Primitive::kPrimVoid; + const uint8_t* annotation = *annotation_ptr; + uint8_t header_byte = *(annotation++); + uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask; + uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift; + int32_t width = value_arg + 1; + annotation_value->type_ = value_type; + + switch (value_type) { + case DexFile::kDexAnnotationByte: + annotation_value->value_.SetB( + static_cast(DexFile::ReadSignedInt(annotation, value_arg))); + primitive_type = Primitive::kPrimByte; + break; + case DexFile::kDexAnnotationShort: + annotation_value->value_.SetS( + static_cast(DexFile::ReadSignedInt(annotation, value_arg))); + primitive_type = Primitive::kPrimShort; + break; + case DexFile::kDexAnnotationChar: + annotation_value->value_.SetC( + static_cast(DexFile::ReadUnsignedInt(annotation, value_arg, false))); + primitive_type = Primitive::kPrimChar; + break; + case DexFile::kDexAnnotationInt: + annotation_value->value_.SetI(DexFile::ReadSignedInt(annotation, value_arg)); + primitive_type = Primitive::kPrimInt; + break; + case DexFile::kDexAnnotationLong: + annotation_value->value_.SetJ(DexFile::ReadSignedLong(annotation, value_arg)); + primitive_type = Primitive::kPrimLong; + break; + case DexFile::kDexAnnotationFloat: + annotation_value->value_.SetI(DexFile::ReadUnsignedInt(annotation, value_arg, true)); + primitive_type = Primitive::kPrimFloat; + break; + case DexFile::kDexAnnotationDouble: + annotation_value->value_.SetJ(DexFile::ReadUnsignedLong(annotation, value_arg, true)); + primitive_type = Primitive::kPrimDouble; + break; + case DexFile::kDexAnnotationBoolean: + annotation_value->value_.SetZ(value_arg != 0); + primitive_type = Primitive::kPrimBoolean; + width = 0; + break; + case DexFile::kDexAnnotationString: { + uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false); + if (result_style == DexFile::kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<1> hs(self); + Handle dex_cache(hs.NewHandle(klass->GetDexCache())); + element_object = Runtime::Current()->GetClassLinker()->ResolveString( + klass->GetDexFile(), index, dex_cache); + set_object = true; + if (element_object == nullptr) { + return false; + } + } + break; + } + case DexFile::kDexAnnotationType: { + uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false); + if (result_style == DexFile::kAllRaw) { + annotation_value->value_.SetI(index); + } else { + element_object = Runtime::Current()->GetClassLinker()->ResolveType( + klass->GetDexFile(), index, klass.Get()); + set_object = true; + if (element_object == nullptr) { + CHECK(self->IsExceptionPending()); + if (result_style == DexFile::kAllObjects) { + const char* msg = dex_file.StringByTypeIdx(index); + self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg); + element_object = self->GetException(); + self->ClearException(); + } else { + return false; + } + } + } + break; + } + case DexFile::kDexAnnotationMethod: { + uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false); + if (result_style == DexFile::kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<2> hs(self); + Handle dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle class_loader(hs.NewHandle(klass->GetClassLoader())); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType( + klass->GetDexFile(), index, dex_cache, class_loader); + if (method == nullptr) { + return false; + } + PointerSize pointer_size = class_linker->GetImagePointerSize(); + set_object = true; + DCHECK(!Runtime::Current()->IsActiveTransaction()); + if (method->IsConstructor()) { + if (pointer_size == PointerSize::k64) { + element_object = mirror::Constructor::CreateFromArtMethod(self, method); + } else { + element_object = mirror::Constructor::CreateFromArtMethod(self, method); + } + } else { + if (pointer_size == PointerSize::k64) { + element_object = mirror::Method::CreateFromArtMethod(self, method); + } else { + element_object = mirror::Method::CreateFromArtMethod(self, method); + } + } + if (element_object == nullptr) { + return false; + } + } + break; + } + case DexFile::kDexAnnotationField: { + uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false); + if (result_style == DexFile::kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<2> hs(self); + Handle dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle class_loader(hs.NewHandle(klass->GetClassLoader())); + ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS( + klass->GetDexFile(), index, dex_cache, class_loader); + if (field == nullptr) { + return false; + } + set_object = true; + PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); + if (pointer_size == PointerSize::k64) { + element_object = mirror::Field::CreateFromArtField(self, field, true); + } else { + element_object = mirror::Field::CreateFromArtField(self, field, true); + } + if (element_object == nullptr) { + return false; + } + } + break; + } + case DexFile::kDexAnnotationEnum: { + uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false); + if (result_style == DexFile::kAllRaw) { + annotation_value->value_.SetI(index); + } else { + StackHandleScope<3> hs(self); + Handle dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle class_loader(hs.NewHandle(klass->GetClassLoader())); + ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField( + klass->GetDexFile(), index, dex_cache, class_loader, true); + if (enum_field == nullptr) { + return false; + } else { + Handle field_class(hs.NewHandle(enum_field->GetDeclaringClass())); + Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, true, true); + element_object = enum_field->GetObject(field_class.Get()); + set_object = true; + } + } + break; + } + case DexFile::kDexAnnotationArray: + if (result_style == DexFile::kAllRaw || array_class.Get() == nullptr) { + return false; + } else { + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<2> hs(self); + uint32_t size = DecodeUnsignedLeb128(&annotation); + Handle component_type(hs.NewHandle(array_class->GetComponentType())); + Handle new_array(hs.NewHandle(mirror::Array::Alloc( + self, array_class.Get(), size, array_class->GetComponentSizeShift(), + Runtime::Current()->GetHeap()->GetCurrentAllocator()))); + if (new_array.Get() == nullptr) { + LOG(ERROR) << "Annotation element array allocation failed with size " << size; + return false; + } + DexFile::AnnotationValue new_annotation_value; + for (uint32_t i = 0; i < size; ++i) { + if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value, + component_type, DexFile::kPrimitivesOrObjects)) { + return false; + } + if (!component_type->IsPrimitive()) { + mirror::Object* obj = new_annotation_value.value_.GetL(); + new_array->AsObjectArray()->SetWithoutChecks(i, obj); + } else { + switch (new_annotation_value.type_) { + case DexFile::kDexAnnotationByte: + new_array->AsByteArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetB()); + break; + case DexFile::kDexAnnotationShort: + new_array->AsShortArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetS()); + break; + case DexFile::kDexAnnotationChar: + new_array->AsCharArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetC()); + break; + case DexFile::kDexAnnotationInt: + new_array->AsIntArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetI()); + break; + case DexFile::kDexAnnotationLong: + new_array->AsLongArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetJ()); + break; + case DexFile::kDexAnnotationFloat: + new_array->AsFloatArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetF()); + break; + case DexFile::kDexAnnotationDouble: + new_array->AsDoubleArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetD()); + break; + case DexFile::kDexAnnotationBoolean: + new_array->AsBooleanArray()->SetWithoutChecks( + i, new_annotation_value.value_.GetZ()); + break; + default: + LOG(FATAL) << "Found invalid annotation value type while building annotation array"; + return false; + } + } + } + element_object = new_array.Get(); + set_object = true; + width = 0; + } + break; + case DexFile::kDexAnnotationAnnotation: + if (result_style == DexFile::kAllRaw) { + return false; + } + element_object = ProcessEncodedAnnotation(klass, &annotation); + if (element_object == nullptr) { + return false; + } + set_object = true; + width = 0; + break; + case DexFile::kDexAnnotationNull: + if (result_style == DexFile::kAllRaw) { + annotation_value->value_.SetI(0); + } else { + CHECK(element_object == nullptr); + set_object = true; + } + width = 0; + break; + default: + LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type); + return false; + } + + annotation += width; + *annotation_ptr = annotation; + + if (result_style == DexFile::kAllObjects && primitive_type != Primitive::kPrimVoid) { + element_object = BoxPrimitive(primitive_type, annotation_value->value_); + set_object = true; + } + + if (set_object) { + annotation_value->value_.SetL(element_object); + } + + return true; +} + +mirror::Object* CreateAnnotationMember(Handle klass, + Handle annotation_class, + const uint8_t** annotation) { + const DexFile& dex_file = klass->GetDexFile(); + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<5> hs(self); + uint32_t element_name_index = DecodeUnsignedLeb128(annotation); + const char* name = dex_file.StringDataByIdx(element_name_index); + Handle string_name( + hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name))); + + PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); + ArtMethod* annotation_method = + annotation_class->FindDeclaredVirtualMethodByName(name, pointer_size); + if (annotation_method == nullptr) { + return nullptr; + } + Handle method_return(hs.NewHandle( + annotation_method->GetReturnType(true /* resolve */, pointer_size))); + + DexFile::AnnotationValue annotation_value; + if (!ProcessAnnotationValue(klass, annotation, &annotation_value, method_return, + DexFile::kAllObjects)) { + return nullptr; + } + Handle value_object(hs.NewHandle(annotation_value.value_.GetL())); + + mirror::Class* annotation_member_class = + WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember); + Handle new_member(hs.NewHandle(annotation_member_class->AllocObject(self))); + mirror::Method* method_obj_ptr; + DCHECK(!Runtime::Current()->IsActiveTransaction()); + if (pointer_size == PointerSize::k64) { + method_obj_ptr = mirror::Method::CreateFromArtMethod( + self, annotation_method); + } else { + method_obj_ptr = mirror::Method::CreateFromArtMethod( + self, annotation_method); + } + Handle method_object(hs.NewHandle(method_obj_ptr)); + + if (new_member.Get() == nullptr || string_name.Get() == nullptr || + method_object.Get() == nullptr || method_return.Get() == nullptr) { + LOG(ERROR) << StringPrintf("Failed creating annotation element (m=%p n=%p a=%p r=%p", + new_member.Get(), string_name.Get(), method_object.Get(), method_return.Get()); + return nullptr; + } + + JValue result; + ArtMethod* annotation_member_init = + soa.DecodeMethod(WellKnownClasses::libcore_reflect_AnnotationMember_init); + uint32_t args[5] = { static_cast(reinterpret_cast(new_member.Get())), + static_cast(reinterpret_cast(string_name.Get())), + static_cast(reinterpret_cast(value_object.Get())), + static_cast(reinterpret_cast(method_return.Get())), + static_cast(reinterpret_cast(method_object.Get())) + }; + annotation_member_init->Invoke(self, args, sizeof(args), &result, "VLLLL"); + if (self->IsExceptionPending()) { + LOG(INFO) << "Exception in AnnotationMember."; + return nullptr; + } + + return new_member.Get(); +} + +const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( + Handle klass, + const DexFile::AnnotationSetItem* annotation_set, + uint32_t visibility, + Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + for (uint32_t i = 0; i < annotation_set->size_; ++i) { + const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i); + if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) { + continue; + } + const uint8_t* annotation = annotation_item->annotation_; + uint32_t type_index = DecodeUnsignedLeb128(&annotation); + mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->ResolveType( + klass->GetDexFile(), type_index, klass.Get()); + if (resolved_class == nullptr) { + std::string temp; + LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d", + klass->GetDescriptor(&temp), type_index); + CHECK(Thread::Current()->IsExceptionPending()); + Thread::Current()->ClearException(); + continue; + } + if (resolved_class == annotation_class.Get()) { + return annotation_item; + } + } + + return nullptr; +} + +mirror::Object* GetAnnotationObjectFromAnnotationSet( + Handle klass, + const DexFile::AnnotationSetItem* annotation_set, + uint32_t visibility, + Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile::AnnotationItem* annotation_item = + GetAnnotationItemFromAnnotationSet(klass, annotation_set, visibility, annotation_class); + if (annotation_item == nullptr) { + return nullptr; + } + const uint8_t* annotation = annotation_item->annotation_; + return ProcessEncodedAnnotation(klass, &annotation); +} + +mirror::Object* GetAnnotationValue(Handle klass, + const DexFile::AnnotationItem* annotation_item, + const char* annotation_name, + Handle array_class, + uint32_t expected_type) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + const uint8_t* annotation = + SearchEncodedAnnotation(dex_file, annotation_item->annotation_, annotation_name); + if (annotation == nullptr) { + return nullptr; + } + DexFile::AnnotationValue annotation_value; + if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, array_class, + DexFile::kAllObjects)) { + return nullptr; + } + if (annotation_value.type_ != expected_type) { + return nullptr; + } + return annotation_value.value_.GetL(); +} + +mirror::ObjectArray* GetSignatureValue(Handle klass, + const DexFile::AnnotationSetItem* annotation_set) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + StackHandleScope<1> hs(Thread::Current()); + const DexFile::AnnotationItem* annotation_item = + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Signature;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + mirror::Class* string_class = mirror::String::GetJavaLangString(); + Handle string_array_class(hs.NewHandle( + Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class))); + if (string_array_class.Get() == nullptr) { + return nullptr; + } + mirror::Object* obj = + GetAnnotationValue(klass, annotation_item, "value", string_array_class, + DexFile::kDexAnnotationArray); + if (obj == nullptr) { + return nullptr; + } + return obj->AsObjectArray(); +} + +mirror::ObjectArray* GetThrowsValue(Handle klass, + const DexFile::AnnotationSetItem* annotation_set) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + StackHandleScope<1> hs(Thread::Current()); + const DexFile::AnnotationItem* annotation_item = + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Throws;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + mirror::Class* class_class = mirror::Class::GetJavaLangClass(); + Handle class_array_class(hs.NewHandle( + Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &class_class))); + if (class_array_class.Get() == nullptr) { + return nullptr; + } + mirror::Object* obj = + GetAnnotationValue(klass, annotation_item, "value", class_array_class, + DexFile::kDexAnnotationArray); + if (obj == nullptr) { + return nullptr; + } + return obj->AsObjectArray(); +} + +mirror::ObjectArray* ProcessAnnotationSet( + Handle klass, + const DexFile::AnnotationSetItem* annotation_set, + uint32_t visibility) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<2> hs(self); + Handle annotation_array_class(hs.NewHandle( + soa.Decode(WellKnownClasses::java_lang_annotation_Annotation__array))); + if (annotation_set == nullptr) { + return mirror::ObjectArray::Alloc(self, annotation_array_class.Get(), 0); + } + + uint32_t size = annotation_set->size_; + Handle> result(hs.NewHandle( + mirror::ObjectArray::Alloc(self, annotation_array_class.Get(), size))); + if (result.Get() == nullptr) { + return nullptr; + } + + uint32_t dest_index = 0; + for (uint32_t i = 0; i < size; ++i) { + const DexFile::AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i); + // Note that we do not use IsVisibilityCompatible here because older code + // was correct for this case. + if (annotation_item->visibility_ != visibility) { + continue; + } + const uint8_t* annotation = annotation_item->annotation_; + mirror::Object* annotation_obj = ProcessEncodedAnnotation(klass, &annotation); + if (annotation_obj != nullptr) { + result->SetWithoutChecks(dest_index, annotation_obj); + ++dest_index; + } else if (self->IsExceptionPending()) { + return nullptr; + } + } + + if (dest_index == size) { + return result.Get(); + } + + mirror::ObjectArray* trimmed_result = + mirror::ObjectArray::Alloc(self, annotation_array_class.Get(), dest_index); + if (trimmed_result == nullptr) { + return nullptr; + } + + for (uint32_t i = 0; i < dest_index; ++i) { + mirror::Object* obj = result->GetWithoutChecks(i); + trimmed_result->SetWithoutChecks(i, obj); + } + + return trimmed_result; +} + +mirror::ObjectArray* ProcessAnnotationSetRefList( + Handle klass, + const DexFile::AnnotationSetRefList* set_ref_list, + uint32_t size) + REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = klass->GetDexFile(); + Thread* self = Thread::Current(); + ScopedObjectAccessUnchecked soa(self); + StackHandleScope<1> hs(self); + mirror::Class* annotation_array_class = + soa.Decode(WellKnownClasses::java_lang_annotation_Annotation__array); + mirror::Class* annotation_array_array_class = + Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class); + if (annotation_array_array_class == nullptr) { + return nullptr; + } + Handle> annotation_array_array(hs.NewHandle( + mirror::ObjectArray::Alloc(self, annotation_array_array_class, size))); + if (annotation_array_array.Get() == nullptr) { + LOG(ERROR) << "Annotation set ref array allocation failed"; + return nullptr; + } + for (uint32_t index = 0; index < size; ++index) { + const DexFile::AnnotationSetRefItem* set_ref_item = &set_ref_list->list_[index]; + const DexFile::AnnotationSetItem* set_item = dex_file.GetSetRefItemItem(set_ref_item); + mirror::Object* annotation_set = ProcessAnnotationSet(klass, set_item, + DexFile::kDexVisibilityRuntime); + if (annotation_set == nullptr) { + return nullptr; + } + annotation_array_array->SetWithoutChecks(index, annotation_set); + } + return annotation_array_array.Get(); +} +} // namespace + +namespace annotations { + +mirror::Object* GetAnnotationForField(ArtField* field, Handle annotation_class) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle field_class(hs.NewHandle(field->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet(field_class, annotation_set, + DexFile::kDexVisibilityRuntime, annotation_class); +} + +mirror::ObjectArray* GetAnnotationsForField(ArtField* field) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + StackHandleScope<1> hs(Thread::Current()); + Handle field_class(hs.NewHandle(field->GetDeclaringClass())); + return ProcessAnnotationSet(field_class, annotation_set, DexFile::kDexVisibilityRuntime); +} + +mirror::ObjectArray* GetSignatureAnnotationForField(ArtField* field) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle field_class(hs.NewHandle(field->GetDeclaringClass())); + return GetSignatureValue(field_class, annotation_set); +} + +bool IsFieldAnnotationPresent(ArtField* field, Handle annotation_class) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field); + if (annotation_set == nullptr) { + return false; + } + StackHandleScope<1> hs(Thread::Current()); + Handle field_class(hs.NewHandle(field->GetDeclaringClass())); + const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( + field_class, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); + return annotation_item != nullptr; +} + +mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) { + const DexFile* dex_file = method->GetDexFile(); + mirror::Class* klass = method->GetDeclaringClass(); + const DexFile::AnnotationsDirectoryItem* annotations_dir = + dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); + if (annotations_dir == nullptr) { + return nullptr; + } + const DexFile::AnnotationSetItem* annotation_set = + dex_file->GetClassAnnotationSet(annotations_dir); + if (annotation_set == nullptr) { + return nullptr; + } + const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet(*dex_file, annotation_set, + "Ldalvik/annotation/AnnotationDefault;", DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + const uint8_t* annotation = + SearchEncodedAnnotation(*dex_file, annotation_item->annotation_, "value"); + if (annotation == nullptr) { + return nullptr; + } + uint8_t header_byte = *(annotation++); + if ((header_byte & DexFile::kDexAnnotationValueTypeMask) != DexFile::kDexAnnotationAnnotation) { + return nullptr; + } + annotation = SearchEncodedAnnotation(*dex_file, annotation, method->GetName()); + if (annotation == nullptr) { + return nullptr; + } + DexFile::AnnotationValue annotation_value; + StackHandleScope<2> hs(Thread::Current()); + Handle h_klass(hs.NewHandle(klass)); + PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); + Handle return_type(hs.NewHandle( + method->GetReturnType(true /* resolve */, pointer_size))); + if (!ProcessAnnotationValue(h_klass, &annotation, &annotation_value, return_type, + DexFile::kAllObjects)) { + return nullptr; + } + return annotation_value.value_.GetL(); +} + +mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle annotation_class) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet(method_class, annotation_set, + DexFile::kDexVisibilityRuntime, annotation_class); +} + +mirror::ObjectArray* GetAnnotationsForMethod(ArtMethod* method) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + StackHandleScope<1> hs(Thread::Current()); + Handle method_class(hs.NewHandle(method->GetDeclaringClass())); + return ProcessAnnotationSet(method_class, annotation_set, DexFile::kDexVisibilityRuntime); +} + +mirror::ObjectArray* GetExceptionTypesForMethod(ArtMethod* method) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetThrowsValue(method_class, annotation_set); +} + +mirror::ObjectArray* GetParameterAnnotations(ArtMethod* method) { + const DexFile* dex_file = method->GetDexFile(); + const DexFile::ParameterAnnotationsItem* parameter_annotations = + FindAnnotationsItemForMethod(method); + if (parameter_annotations == nullptr) { + return nullptr; + } + const DexFile::AnnotationSetRefList* set_ref_list = + dex_file->GetParameterAnnotationSetRefList(parameter_annotations); + if (set_ref_list == nullptr) { + return nullptr; + } + uint32_t size = set_ref_list->size_; + StackHandleScope<1> hs(Thread::Current()); + Handle method_class(hs.NewHandle(method->GetDeclaringClass())); + return ProcessAnnotationSetRefList(method_class, set_ref_list, size); +} + +mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method, + uint32_t parameter_idx, + Handle annotation_class) { + const DexFile* dex_file = method->GetDexFile(); + const DexFile::ParameterAnnotationsItem* parameter_annotations = + FindAnnotationsItemForMethod(method); + if (parameter_annotations == nullptr) { + return nullptr; + } + const DexFile::AnnotationSetRefList* set_ref_list = + dex_file->GetParameterAnnotationSetRefList(parameter_annotations); + if (set_ref_list == nullptr) { + return nullptr; + } + if (parameter_idx >= set_ref_list->size_) { + return nullptr; + } + const DexFile::AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx]; + const DexFile::AnnotationSetItem* annotation_set = + dex_file->GetSetRefItemItem(annotation_set_ref); + + StackHandleScope<1> hs(Thread::Current()); + Handle method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetAnnotationObjectFromAnnotationSet(method_class, + annotation_set, + DexFile::kDexVisibilityRuntime, + annotation_class); +} + +mirror::ObjectArray* GetSignatureAnnotationForMethod(ArtMethod* method) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + if (annotation_set == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + Handle method_class(hs.NewHandle(method->GetDeclaringClass())); + return GetSignatureValue(method_class, annotation_set); +} + +bool IsMethodAnnotationPresent(ArtMethod* method, Handle annotation_class, + uint32_t visibility /* = DexFile::kDexVisibilityRuntime */) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method); + if (annotation_set == nullptr) { + return false; + } + StackHandleScope<1> hs(Thread::Current()); + Handle method_class(hs.NewHandle(method->GetDeclaringClass())); + const DexFile::AnnotationItem* annotation_item = + GetAnnotationItemFromAnnotationSet(method_class, annotation_set, visibility, + annotation_class); + return annotation_item != nullptr; +} + +mirror::Object* GetAnnotationForClass(Handle klass, + Handle annotation_class) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return nullptr; + } + return GetAnnotationObjectFromAnnotationSet(klass, annotation_set, DexFile::kDexVisibilityRuntime, + annotation_class); +} + +mirror::ObjectArray* GetAnnotationsForClass(Handle klass) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + return ProcessAnnotationSet(klass, annotation_set, DexFile::kDexVisibilityRuntime); +} + +mirror::ObjectArray* GetDeclaredClasses(Handle klass) { + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return nullptr; + } + const DexFile::AnnotationItem* annotation_item = + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/MemberClasses;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + StackHandleScope<1> hs(Thread::Current()); + mirror::Class* class_class = mirror::Class::GetJavaLangClass(); + Handle class_array_class(hs.NewHandle( + Runtime::Current()->GetClassLinker()->FindArrayClass(hs.Self(), &class_class))); + if (class_array_class.Get() == nullptr) { + return nullptr; + } + mirror::Object* obj = + GetAnnotationValue(klass, annotation_item, "value", class_array_class, + DexFile::kDexAnnotationArray); + if (obj == nullptr) { + return nullptr; + } + return obj->AsObjectArray(); +} + +mirror::Class* GetDeclaringClass(Handle klass) { + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return nullptr; + } + const DexFile::AnnotationItem* annotation_item = + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingClass;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + mirror::Object* obj = GetAnnotationValue(klass, annotation_item, "value", + ScopedNullHandle(), + DexFile::kDexAnnotationType); + if (obj == nullptr) { + return nullptr; + } + return obj->AsClass(); +} + +mirror::Class* GetEnclosingClass(Handle klass) { + const DexFile& dex_file = klass->GetDexFile(); + mirror::Class* declaring_class = GetDeclaringClass(klass); + if (declaring_class != nullptr) { + return declaring_class; + } + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return nullptr; + } + const DexFile::AnnotationItem* annotation_item = + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingMethod;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + const uint8_t* annotation = + SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "value"); + if (annotation == nullptr) { + return nullptr; + } + DexFile::AnnotationValue annotation_value; + if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, + ScopedNullHandle(), DexFile::kAllRaw)) { + return nullptr; + } + if (annotation_value.type_ != DexFile::kDexAnnotationMethod) { + return nullptr; + } + StackHandleScope<2> hs(Thread::Current()); + Handle dex_cache(hs.NewHandle(klass->GetDexCache())); + Handle class_loader(hs.NewHandle(klass->GetClassLoader())); + ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType( + klass->GetDexFile(), annotation_value.value_.GetI(), dex_cache, class_loader); + if (method == nullptr) { + return nullptr; + } + return method->GetDeclaringClass(); +} + +mirror::Object* GetEnclosingMethod(Handle klass) { + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return nullptr; + } + const DexFile::AnnotationItem* annotation_item = + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/EnclosingMethod;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + return GetAnnotationValue(klass, annotation_item, "value", ScopedNullHandle(), + DexFile::kDexAnnotationMethod); +} + +bool GetInnerClass(Handle klass, mirror::String** name) { + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return false; + } + const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet( + dex_file, annotation_set, "Ldalvik/annotation/InnerClass;", DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return false; + } + const uint8_t* annotation = + SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "name"); + if (annotation == nullptr) { + return false; + } + DexFile::AnnotationValue annotation_value; + if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, + ScopedNullHandle(), + DexFile::kAllObjects)) { + return false; + } + if (annotation_value.type_ != DexFile::kDexAnnotationNull && + annotation_value.type_ != DexFile::kDexAnnotationString) { + return false; + } + *name = down_cast(annotation_value.value_.GetL()); + return true; +} + +bool GetInnerClassFlags(Handle klass, uint32_t* flags) { + const DexFile& dex_file = klass->GetDexFile(); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return false; + } + const DexFile::AnnotationItem* annotation_item = + SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/InnerClass;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return false; + } + const uint8_t* annotation = + SearchEncodedAnnotation(dex_file, annotation_item->annotation_, "accessFlags"); + if (annotation == nullptr) { + return false; + } + DexFile::AnnotationValue annotation_value; + if (!ProcessAnnotationValue(klass, &annotation, &annotation_value, + ScopedNullHandle(), DexFile::kAllRaw)) { + return false; + } + if (annotation_value.type_ != DexFile::kDexAnnotationInt) { + return false; + } + *flags = annotation_value.value_.GetI(); + return true; +} + +mirror::ObjectArray* GetSignatureAnnotationForClass(Handle klass) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return nullptr; + } + return GetSignatureValue(klass, annotation_set); +} + +bool IsClassAnnotationPresent(Handle klass, Handle annotation_class) { + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(klass); + if (annotation_set == nullptr) { + return false; + } + const DexFile::AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet( + klass, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class); + return annotation_item != nullptr; +} + +int32_t GetLineNumFromPC(const DexFile* dex_file, ArtMethod* method, uint32_t rel_pc) { + // For native method, lineno should be -2 to indicate it is native. Note that + // "line number == -2" is how libcore tells from StackTraceElement. + if (method->GetCodeItemOffset() == 0) { + return -2; + } + + const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset()); + DCHECK(code_item != nullptr) << PrettyMethod(method) << " " << dex_file->GetLocation(); + + // A method with no line number info should return -1 + DexFile::LineNumFromPcContext context(rel_pc, -1); + dex_file->DecodeDebugPositionInfo(code_item, DexFile::LineNumForPcCb, &context); + return context.line_num_; +} + +template +void RuntimeEncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const { + DCHECK(dex_cache_ != nullptr); + DCHECK(class_loader_ != nullptr); + switch (type_) { + case kBoolean: field->SetBoolean(field->GetDeclaringClass(), jval_.z); + break; + case kByte: field->SetByte(field->GetDeclaringClass(), jval_.b); break; + case kShort: field->SetShort(field->GetDeclaringClass(), jval_.s); break; + case kChar: field->SetChar(field->GetDeclaringClass(), jval_.c); break; + case kInt: field->SetInt(field->GetDeclaringClass(), jval_.i); break; + case kLong: field->SetLong(field->GetDeclaringClass(), jval_.j); break; + case kFloat: field->SetFloat(field->GetDeclaringClass(), jval_.f); break; + case kDouble: field->SetDouble(field->GetDeclaringClass(), jval_.d); break; + case kNull: field->SetObject(field->GetDeclaringClass(), nullptr); break; + case kString: { + mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_); + field->SetObject(field->GetDeclaringClass(), resolved); + break; + } + case kType: { + mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_, + *class_loader_); + field->SetObject(field->GetDeclaringClass(), resolved); + break; + } + default: UNIMPLEMENTED(FATAL) << ": type " << type_; + } +} +template +void RuntimeEncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const; +template +void RuntimeEncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const; + +} // namespace annotations + +} // namespace art diff --git a/runtime/dex_file_annotations.h b/runtime/dex_file_annotations.h new file mode 100644 index 000000000..7b4e8564b --- /dev/null +++ b/runtime/dex_file_annotations.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 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. + */ + +#ifndef ART_RUNTIME_DEX_FILE_ANNOTATIONS_H_ +#define ART_RUNTIME_DEX_FILE_ANNOTATIONS_H_ + +#include "dex_file.h" + +#include "mirror/object_array.h" + +namespace art { + +namespace mirror { + class ClassLoader; + class DexCache; +} // namespace mirror +class ArtField; +class ArtMethod; +class ClassLinker; + +namespace annotations { + +// Field annotations. +mirror::Object* GetAnnotationForField(ArtField* field, Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetAnnotationsForField(ArtField* field) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetSignatureAnnotationForField(ArtField* field) + REQUIRES_SHARED(Locks::mutator_lock_); +bool IsFieldAnnotationPresent(ArtField* field, Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_); + +// Method annotations. +mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetAnnotationsForMethod(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetExceptionTypesForMethod(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetParameterAnnotations(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::Object* GetAnnotationForMethodParameter(ArtMethod* method, + uint32_t parameter_idx, + Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetSignatureAnnotationForMethod(ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_); +bool IsMethodAnnotationPresent(ArtMethod* method, Handle annotation_class, + uint32_t visibility = DexFile::kDexVisibilityRuntime) + REQUIRES_SHARED(Locks::mutator_lock_); + +// Class annotations. +mirror::Object* GetAnnotationForClass(Handle klass, + Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetAnnotationsForClass(Handle klass) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetDeclaredClasses(Handle klass) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::Class* GetDeclaringClass(Handle klass) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::Class* GetEnclosingClass(Handle klass) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::Object* GetEnclosingMethod(Handle klass) + REQUIRES_SHARED(Locks::mutator_lock_); +bool GetInnerClass(Handle klass, mirror::String** name) + REQUIRES_SHARED(Locks::mutator_lock_); +bool GetInnerClassFlags(Handle klass, uint32_t* flags) + REQUIRES_SHARED(Locks::mutator_lock_); +mirror::ObjectArray* GetSignatureAnnotationForClass(Handle klass) + REQUIRES_SHARED(Locks::mutator_lock_); +bool IsClassAnnotationPresent(Handle klass, + Handle annotation_class) + REQUIRES_SHARED(Locks::mutator_lock_); + +// Map back from a PC to the line number in a method. +int32_t GetLineNumFromPC(const DexFile* dex_file, ArtMethod* method, uint32_t rel_pc) + REQUIRES_SHARED(Locks::mutator_lock_); + +// Annotations iterator. +class RuntimeEncodedStaticFieldValueIterator : public EncodedStaticFieldValueIterator { + public: + // A constructor meant to be called from runtime code. + RuntimeEncodedStaticFieldValueIterator(const DexFile& dex_file, + Handle* dex_cache, + Handle* class_loader, + ClassLinker* linker, + const DexFile::ClassDef& class_def) + REQUIRES_SHARED(Locks::mutator_lock_) + : EncodedStaticFieldValueIterator(dex_file, class_def), + dex_cache_(dex_cache), + class_loader_(class_loader), + linker_(linker) { + } + + template + void ReadValueToField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_); + + private: + Handle* const dex_cache_; // Dex cache to resolve literal objects. + Handle* const class_loader_; // ClassLoader to resolve types. + ClassLinker* linker_; // Linker to resolve literal objects. + DISALLOW_IMPLICIT_CONSTRUCTORS(RuntimeEncodedStaticFieldValueIterator); +}; + +} // namespace annotations + +} // namespace art + +#endif // ART_RUNTIME_DEX_FILE_ANNOTATIONS_H_ diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index c6144086a..d505aea10 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -402,7 +402,7 @@ void UnstartedRuntime::UnstartedClassGetEnclosingClass( if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { result->SetL(nullptr); } - result->SetL(klass->GetDexFile().GetEnclosingClass(klass)); + result->SetL(annotations::GetEnclosingClass(klass)); } void UnstartedRuntime::UnstartedClassGetInnerClassFlags( diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h index 417a18585..52c3843a6 100644 --- a/runtime/jit/jit.h +++ b/runtime/jit/jit.h @@ -30,6 +30,7 @@ namespace art { class ArtMethod; +class ClassLinker; struct RuntimeArgumentMap; union JValue; diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index c979c2813..213297899 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -23,6 +23,7 @@ #include "class-inl.h" #include "dex_cache.h" #include "dex_file-inl.h" +#include "dex_file_annotations.h" #include "gc/accounting/card_table-inl.h" #include "handle_scope-inl.h" #include "method.h" @@ -1214,7 +1215,7 @@ int32_t Class::GetInnerClassFlags(Handle h_this, int32_t default_value) { return default_value; } uint32_t flags; - if (!h_this->GetDexFile().GetInnerClassFlags(h_this, &flags)) { + if (!annotations::GetInnerClassFlags(h_this, &flags)) { return default_value; } return flags; diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index d89a334f3..2b2fe0c7d 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -23,6 +23,7 @@ #include "class_linker.h" #include "common_throws.h" #include "dex_file-inl.h" +#include "dex_file_annotations.h" #include "jni_internal.h" #include "nth_caller_visitor.h" #include "mirror/class-inl.h" @@ -454,7 +455,7 @@ static jobject Class_getDeclaredAnnotation(JNIEnv* env, jobject javaThis, jclass } Handle annotation_class(hs.NewHandle(soa.Decode(annotationClass))); return soa.AddLocalReference( - klass->GetDexFile().GetAnnotationForClass(klass, annotation_class)); + annotations::GetAnnotationForClass(klass, annotation_class)); } static jobjectArray Class_getDeclaredAnnotations(JNIEnv* env, jobject javaThis) { @@ -469,7 +470,7 @@ static jobjectArray Class_getDeclaredAnnotations(JNIEnv* env, jobject javaThis) mirror::ObjectArray::Alloc(soa.Self(), annotation_array_class, 0); return soa.AddLocalReference(empty_array); } - return soa.AddLocalReference(klass->GetDexFile().GetAnnotationsForClass(klass)); + return soa.AddLocalReference(annotations::GetAnnotationsForClass(klass)); } static jobjectArray Class_getDeclaredClasses(JNIEnv* env, jobject javaThis) { @@ -478,7 +479,7 @@ static jobjectArray Class_getDeclaredClasses(JNIEnv* env, jobject javaThis) { Handle klass(hs.NewHandle(DecodeClass(soa, javaThis))); mirror::ObjectArray* classes = nullptr; if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) { - classes = klass->GetDexFile().GetDeclaredClasses(klass); + classes = annotations::GetDeclaredClasses(klass); } if (classes == nullptr) { // Return an empty array instead of a null pointer. @@ -506,7 +507,7 @@ static jclass Class_getEnclosingClass(JNIEnv* env, jobject javaThis) { if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { return nullptr; } - return soa.AddLocalReference(klass->GetDexFile().GetEnclosingClass(klass)); + return soa.AddLocalReference(annotations::GetEnclosingClass(klass)); } static jobject Class_getEnclosingConstructorNative(JNIEnv* env, jobject javaThis) { @@ -516,7 +517,7 @@ static jobject Class_getEnclosingConstructorNative(JNIEnv* env, jobject javaThis if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { return nullptr; } - mirror::Object* method = klass->GetDexFile().GetEnclosingMethod(klass); + mirror::Object* method = annotations::GetEnclosingMethod(klass); if (method != nullptr) { if (method->GetClass() == soa.Decode(WellKnownClasses::java_lang_reflect_Constructor)) { @@ -533,7 +534,7 @@ static jobject Class_getEnclosingMethodNative(JNIEnv* env, jobject javaThis) { if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { return nullptr; } - mirror::Object* method = klass->GetDexFile().GetEnclosingMethod(klass); + mirror::Object* method = annotations::GetEnclosingMethod(klass); if (method != nullptr) { if (method->GetClass() == soa.Decode(WellKnownClasses::java_lang_reflect_Method)) { @@ -558,7 +559,7 @@ static jstring Class_getInnerClassName(JNIEnv* env, jobject javaThis) { return nullptr; } mirror::String* class_name = nullptr; - if (!klass->GetDexFile().GetInnerClass(klass, &class_name)) { + if (!annotations::GetInnerClass(klass, &class_name)) { return nullptr; } return soa.AddLocalReference(class_name); @@ -572,7 +573,7 @@ static jobjectArray Class_getSignatureAnnotation(JNIEnv* env, jobject javaThis) return nullptr; } return soa.AddLocalReference( - klass->GetDexFile().GetSignatureAnnotationForClass(klass)); + annotations::GetSignatureAnnotationForClass(klass)); } static jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) { @@ -583,7 +584,7 @@ static jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) { return false; } mirror::String* class_name = nullptr; - if (!klass->GetDexFile().GetInnerClass(klass, &class_name)) { + if (!annotations::GetInnerClass(klass, &class_name)) { return false; } return class_name == nullptr; @@ -598,7 +599,7 @@ static jboolean Class_isDeclaredAnnotationPresent(JNIEnv* env, jobject javaThis, return false; } Handle annotation_class(hs.NewHandle(soa.Decode(annotationType))); - return klass->GetDexFile().IsClassAnnotationPresent(klass, annotation_class); + return annotations::IsClassAnnotationPresent(klass, annotation_class); } static jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) { @@ -612,7 +613,7 @@ static jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) { if (Class_isAnonymousClass(env, javaThis)) { return nullptr; } - return soa.AddLocalReference(klass->GetDexFile().GetDeclaringClass(klass)); + return soa.AddLocalReference(annotations::GetDeclaringClass(klass)); } static jobject Class_newInstance(JNIEnv* env, jobject javaThis) { diff --git a/runtime/native/java_lang_reflect_AbstractMethod.cc b/runtime/native/java_lang_reflect_AbstractMethod.cc index 33e0daef1..254f8dbb4 100644 --- a/runtime/native/java_lang_reflect_AbstractMethod.cc +++ b/runtime/native/java_lang_reflect_AbstractMethod.cc @@ -17,6 +17,7 @@ #include "java_lang_reflect_AbstractMethod.h" #include "art_method-inl.h" +#include "dex_file_annotations.h" #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -38,7 +39,7 @@ static jobjectArray AbstractMethod_getDeclaredAnnotations(JNIEnv* env, jobject j mirror::ObjectArray::Alloc(soa.Self(), annotation_array_class, 0); return soa.AddLocalReference(empty_array); } - return soa.AddLocalReference(method->GetDexFile()->GetAnnotationsForMethod(method)); + return soa.AddLocalReference(annotations::GetAnnotationsForMethod(method)); } static jobject AbstractMethod_getAnnotationNative(JNIEnv* env, @@ -51,8 +52,7 @@ static jobject AbstractMethod_getAnnotationNative(JNIEnv* env, return nullptr; } else { Handle klass(hs.NewHandle(soa.Decode(annotationType))); - return soa.AddLocalReference( - method->GetDexFile()->GetAnnotationForMethod(method, klass)); + return soa.AddLocalReference(annotations::GetAnnotationForMethod(method, klass)); } } @@ -63,8 +63,7 @@ static jobjectArray AbstractMethod_getSignatureAnnotation(JNIEnv* env, jobject j return nullptr; } StackHandleScope<1> hs(soa.Self()); - return soa.AddLocalReference( - method->GetDexFile()->GetSignatureAnnotationForMethod(method)); + return soa.AddLocalReference(annotations::GetSignatureAnnotationForMethod(method)); } @@ -74,8 +73,7 @@ static jobjectArray AbstractMethod_getParameterAnnotationsNative(JNIEnv* env, jo if (method->IsProxyMethod()) { return nullptr; } else { - return soa.AddLocalReference( - method->GetDexFile()->GetParameterAnnotations(method)); + return soa.AddLocalReference(annotations::GetParameterAnnotations(method)); } } @@ -89,7 +87,7 @@ static jboolean AbstractMethod_isAnnotationPresentNative(JNIEnv* env, } StackHandleScope<1> hs(soa.Self()); Handle klass(hs.NewHandle(soa.Decode(annotationType))); - return method->GetDexFile()->IsMethodAnnotationPresent(method, klass); + return annotations::IsMethodAnnotationPresent(method, klass); } static JNINativeMethod gMethods[] = { diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc index f699d6bd7..d001d0c0d 100644 --- a/runtime/native/java_lang_reflect_Constructor.cc +++ b/runtime/native/java_lang_reflect_Constructor.cc @@ -20,6 +20,7 @@ #include "base/enums.h" #include "class_linker.h" #include "class_linker-inl.h" +#include "dex_file_annotations.h" #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/method.h" @@ -35,7 +36,7 @@ static jobjectArray Constructor_getExceptionTypes(JNIEnv* env, jobject javaMetho ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod) ->GetInterfaceMethodIfProxy(kRuntimePointerSize); mirror::ObjectArray* result_array = - method->GetDexFile()->GetExceptionTypesForMethod(method); + annotations::GetExceptionTypesForMethod(method); if (result_array == nullptr) { // Return an empty array instead of a null pointer. mirror::Class* class_class = mirror::Class::GetJavaLangClass(); diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index 5a4ced2fe..412445f0d 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -20,6 +20,7 @@ #include "class_linker-inl.h" #include "common_throws.h" #include "dex_file-inl.h" +#include "dex_file_annotations.h" #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/field.h" @@ -423,7 +424,7 @@ static jobject Field_getAnnotationNative(JNIEnv* env, jobject javaField, jclass return nullptr; } Handle klass(hs.NewHandle(soa.Decode(annotationType))); - return soa.AddLocalReference(field->GetDexFile()->GetAnnotationForField(field, klass)); + return soa.AddLocalReference(annotations::GetAnnotationForField(field, klass)); } static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) { @@ -437,7 +438,7 @@ static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) mirror::ObjectArray::Alloc(soa.Self(), annotation_array_class, 0); return soa.AddLocalReference(empty_array); } - return soa.AddLocalReference(field->GetDexFile()->GetAnnotationsForField(field)); + return soa.AddLocalReference(annotations::GetAnnotationsForField(field)); } static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField) { @@ -446,8 +447,7 @@ static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField) if (field->GetDeclaringClass()->IsProxyClass()) { return nullptr; } - return soa.AddLocalReference( - field->GetDexFile()->GetSignatureAnnotationForField(field)); + return soa.AddLocalReference(annotations::GetSignatureAnnotationForField(field)); } static jboolean Field_isAnnotationPresentNative(JNIEnv* env, jobject javaField, @@ -459,7 +459,7 @@ static jboolean Field_isAnnotationPresentNative(JNIEnv* env, jobject javaField, return false; } Handle klass(hs.NewHandle(soa.Decode(annotationType))); - return field->GetDexFile()->IsFieldAnnotationPresent(field, klass); + return annotations::IsFieldAnnotationPresent(field, klass); } static JNINativeMethod gMethods[] = { diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc index 3360f4170..b8efb1490 100644 --- a/runtime/native/java_lang_reflect_Method.cc +++ b/runtime/native/java_lang_reflect_Method.cc @@ -20,6 +20,7 @@ #include "base/enums.h" #include "class_linker.h" #include "class_linker-inl.h" +#include "dex_file_annotations.h" #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -36,7 +37,7 @@ static jobject Method_getDefaultValue(JNIEnv* env, jobject javaMethod) { if (!method->GetDeclaringClass()->IsAnnotation()) { return nullptr; } - return soa.AddLocalReference(method->GetDexFile()->GetAnnotationDefaultValue(method)); + return soa.AddLocalReference(annotations::GetAnnotationDefaultValue(method)); } static jobjectArray Method_getExceptionTypes(JNIEnv* env, jobject javaMethod) { @@ -58,7 +59,7 @@ static jobjectArray Method_getExceptionTypes(JNIEnv* env, jobject javaMethod) { return soa.AddLocalReference(declared_exceptions->Clone(soa.Self())); } else { mirror::ObjectArray* result_array = - method->GetDexFile()->GetExceptionTypesForMethod(method); + annotations::GetExceptionTypesForMethod(method); if (result_array == nullptr) { // Return an empty array instead of a null pointer mirror::Class* class_class = mirror::Class::GetJavaLangClass(); diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc index 8fe3bb590..c2a803c3c 100644 --- a/runtime/native/java_lang_reflect_Parameter.cc +++ b/runtime/native/java_lang_reflect_Parameter.cc @@ -19,6 +19,7 @@ #include "art_method-inl.h" #include "common_throws.h" #include "dex_file-inl.h" +#include "dex_file_annotations.h" #include "jni_internal.h" #include "scoped_fast_native_object_access.h" #include "utils.h" @@ -54,7 +55,7 @@ static jobject Parameter_getAnnotationNative(JNIEnv* env, StackHandleScope<1> hs(soa.Self()); Handle klass(hs.NewHandle(soa.Decode(annotationType))); return soa.AddLocalReference( - method->GetDexFile()->GetAnnotationForMethodParameter(method, parameterIndex, klass)); + annotations::GetAnnotationForMethodParameter(method, parameterIndex, klass)); } static JNINativeMethod gMethods[] = { diff --git a/runtime/quick/inline_method_analyser.h b/runtime/quick/inline_method_analyser.h index 356e29084..2df2ced7f 100644 --- a/runtime/quick/inline_method_analyser.h +++ b/runtime/quick/inline_method_analyser.h @@ -33,6 +33,7 @@ namespace art { namespace verifier { class MethodVerifier; } // namespace verifier +class ArtMethod; enum InlineMethodOpcode : uint16_t { kIntrinsicDoubleCvt, diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 55aba2bef..b3f29c28e 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -160,8 +160,8 @@ void QuickExceptionHandler::FindCatch(mirror::Throwable* exception) { LOG(INFO) << "Handler is upcall"; } if (handler_method_ != nullptr) { - const DexFile& dex_file = *handler_method_->GetDeclaringClass()->GetDexCache()->GetDexFile(); - int line_number = dex_file.GetLineNumFromPC(handler_method_, handler_dex_pc_); + const DexFile* dex_file = handler_method_->GetDeclaringClass()->GetDexCache()->GetDexFile(); + int line_number = annotations::GetLineNumFromPC(dex_file, handler_method_, handler_dex_pc_); LOG(INFO) << "Handler: " << PrettyMethod(handler_method_) << " (line: " << line_number << ")"; } } diff --git a/runtime/thread.cc b/runtime/thread.cc index a860c7ae9..89403545f 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -40,6 +40,7 @@ #include "class_linker-inl.h" #include "debugger.h" #include "dex_file-inl.h" +#include "dex_file_annotations.h" #include "entrypoints/entrypoint_utils.h" #include "entrypoints/quick/quick_alloc_entrypoints.h" #include "gc/accounting/card_table-inl.h" @@ -1388,8 +1389,8 @@ struct StackDumpVisitor : public StackVisitor { mirror::DexCache* dex_cache = c->GetDexCache(); int line_number = -1; if (dex_cache != nullptr) { // be tolerant of bad input - const DexFile& dex_file = *dex_cache->GetDexFile(); - line_number = dex_file.GetLineNumFromPC(m, GetDexPc(false)); + const DexFile* dex_file = dex_cache->GetDexFile(); + line_number = annotations::GetLineNumFromPC(dex_file, m, GetDexPc(false)); } if (line_number == last_line_number && last_method == m) { ++repetition_count; -- 2.11.0