首页
社区
课程
招聘
[原创]加壳脱壳知识点总结--类加载、方法执行流程以及脱壳实战
发表于: 2024-6-11 18:12 6328

[原创]加壳脱壳知识点总结--类加载、方法执行流程以及脱壳实战

2024-6-11 18:12
6328

总结记录下ART环境下App启动流程中类加载流程以及相关知识,分析更深层次的脱壳点,加深对App加壳以及脱壳原理的理解。
环境:Android 8.0.0

这里直接从loadClass开始,DexClassloader,PathClassloader,InMemoryDexClassLoader这三个类的父类是BaseDexClassLoader,BaseDexClassLoader的父类是Classloader,在ClassLoader这个类里实现了loadClass。

protected Class<?> loadClass(String name, boolean resolve),这里官方的源码注释解释的比较清楚了,首先确定这个类是否被加载过,没有的话会开始走双亲委派的流程调用parent.loadClass,如果父加载器都没有加载过,则自己调用findClass开始查找class并加载

findClass在BaseDexClassLoader中重写了

DexPathList_public Class<?> findClass(String name, List<Throwable> suppressed) 这里的dexElements是在加载Dex时赋值的,保存的时当时加载的DexFile

Element_public Class<?> findClass(String name, ClassLoader definingContext,List<Throwable> suppressed),这个Element类是DexPathList的一个内部类

DexFile_loadClassBinaryName

DexFile_defineClass

DexFile_defineClassNative 这里进入了native层的DexFile中,这段代码在进行DexFile的注册。

__mirror::Class* ClassLinker::DefineClass__这里也是在初始化类,分配类空间等,有三个阶段SetupClass,LoadClass,LinkClass,关于类加载主要看LoadClass主要作用是将类的字段和方法信息从Dex文件中加载到内存中,并建立相应的数据结构。

ClassLinker::LoadClass

ClassLinker::LoadClassMembers 这里开始加载类的成员变量,方法,方法的加载有两步LoadMethod和LinkCode。

ClassLinker::LoadMethod LoadMethod为ArtMethod的基础属性赋值,并检查是否是构造函数,这里可以看到在设置CodeItemOffset,以前的函数抽取壳会在这个阶段回填字节码,通过hook LoadMethod即可脱到完整的Dex。

ClassLinker::LinkCode LinkCode的主要工作是把,以及一些相关操作例如分配空间,关联引用等,还有Native函数的绑定,最后会调用SetEntryPointFromQuickCompiledCode设置方法被调用时的入口,method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge())这段代码就是当oat被阻断后会把方法入口设置为解释执行入口。

类加载完成之后,一般就要调用类的方法了,所以继续看一下方法执行的流程,Android 8.0中主要是两种方法执行方式,解释执行和OAT的快速执行,解释执行主要是根据字节码执行方法,快速执行通过OAT中预先编译成的本地机器码来执行方法,对于加壳来说,阻断了OAT流程后系统会转向解释执行。

在安卓中,Java 函数可以通过两种主要的方式进行调用。一种是通过自然的代码执行路径进行调用,即在 Java 虚拟机中直接调用,另一种是通过 JNI进行调用,即通过本地代码与 Java 代码进行交互来实现函数调用,先说JNI调用的流程。
JNI调用Java函数主要是通过一系列的CallXXXMethod(+V代表无返回值+A代表参数以数组形式传递)JNI函数,这里找几个看一下实现方式,可以看到都调用了InvokeVirtualOrInterfaceWithVarArgs。

InvokeVirtualOrInterfaceWithVarArgs

InvokeWithArgArray

ArtMethod::invoke

这就到了比较关键的地方,通过反射和JNI调用都会走到这里,Invoke会判断方法调用的环境,方法类型,如果不是静态方法会进入art_quick_invoke_stub若目标方法已编译为快速路径,则经 INVOKE_STUB_CALL_AND_RETURN的汇编代码后,通过 PtrSizedFields 中的 entry_point_from_quick_compiled_code_ 跳转到目标方法的入口(entry_point_from_quick_compiled_code_ 也是自然通过代码执行Java代码的入口)。
这里有两种入口,一种是编译好的本地机器指令入口直接开始执行,另一种就是解释执行入口,在LinkCode函数说到当OAT被阻断后会调用method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge()),这样的话entry_point_from_quick_compiled_code_ 所指向的就是art_quick_to_interpreter_bridge这个桥函数了,这个桥函数也是汇编实现。

通过bl跳转到了artQuickToInterpreterBridge函数,之后的调用流程是artQuickToInterpreterBridge() → interpreter::EnterInterpreterFromEntryPoint() → interpreter::Execute()。

interpreter::Execute()

解释执行会通过kInterpreterImplKind的类型来判断执行哪种解释器,解释执行总的来说有三种方式goto型,汇编型和switch型,这三种的实现方式其实就和字面意思差不多,分别使用goto,汇编,switch来完成对字节码匹配执行,goto型在较早的版本还有,在本次分析的安卓8系统中已经不存在了,安卓8实现了汇编型和switch型,默认使用汇编型。

上面分析了类的加载流程和Java方法的调用流程,这里面大量出现了Dexfile,ArtMethod,两个地方都是可以用于脱壳,通过Dexfile可以直接dump Dexfile,而通过ArtMethod也可以间接获取到Dexfile对象,这里随便找一个,loadClassMember方法进行实战,还是用的frida hook的方式。
这里代码用上次的改一下即可

图片描述
图片描述

其实总结的知识点已经涉及到抽取壳脱壳了,抽取壳的脱壳后面再写。

https://blog.csdn.net/u013989732/article/details/80670989
https://blog.csdn.net/hl09083253cy/article/details/78418651
https://blog.csdn.net/hl09083253cy/article/details/78418702
https://rk700.github.io/2017/06/30/hook-on-android-n/
https://blog.csdn.net/u013989732/article/details/80717762/

public Class<?> loadClass(String name) throws ClassNotFoundException {
       return loadClass(name, false);
  }
public Class<?> loadClass(String name) throws ClassNotFoundException {
       return loadClass(name, false);
  }
protected Class<?> loadClass(String name, boolean resolve)
       throws ClassNotFoundException
{
           // First, check if the class has already been loaded
           Class<?> c = findLoadedClass(name);
           if (c == null) {
               try {
                   if (parent != null) {
                       c = parent.loadClass(name, false);
                  } else {
                       c = findBootstrapClassOrNull(name);
                   }
               } catch (ClassNotFoundException e) {
                   // ClassNotFoundException thrown if class not found
                   // from the non-null parent class loader
               }
 
               if (c == null) {
                   // If still not found, then invoke findClass in order
                   // to find the class.
                   c = findClass(name);
               }
           }
           return c;
   }
protected Class<?> loadClass(String name, boolean resolve)
       throws ClassNotFoundException
{
           // First, check if the class has already been loaded
           Class<?> c = findLoadedClass(name);
           if (c == null) {
               try {
                   if (parent != null) {
                       c = parent.loadClass(name, false);
                  } else {
                       c = findBootstrapClassOrNull(name);
                   }
               } catch (ClassNotFoundException e) {
                   // ClassNotFoundException thrown if class not found
                   // from the non-null parent class loader
               }
 
               if (c == null) {
                   // If still not found, then invoke findClass in order
                   // to find the class.
                   c = findClass(name);
               }
           }
           return c;
   }
@Override
 protected Class<?> findClass(String name) throws ClassNotFoundException {
     List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
     Class c = pathList.findClass(name, suppressedExceptions);
     if (c == null) {
         ClassNotFoundException cnfe = new ClassNotFoundException(
                 "Didn't find class \"" + name + "\" on path: " + pathList);
         for (Throwable t : suppressedExceptions) {
             cnfe.addSuppressed(t);
         }
         throw cnfe;
     }
     return c;
 }
@Override
 protected Class<?> findClass(String name) throws ClassNotFoundException {
     List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
     Class c = pathList.findClass(name, suppressedExceptions);
     if (c == null) {
         ClassNotFoundException cnfe = new ClassNotFoundException(
                 "Didn't find class \"" + name + "\" on path: " + pathList);
         for (Throwable t : suppressedExceptions) {
             cnfe.addSuppressed(t);
         }
         throw cnfe;
     }
     return c;
 }
public Class<?> findClass(String name, List<Throwable> suppressed) {
       for (Element element : dexElements) {
           Class<?> clazz = element.findClass(name, definingContext, suppressed);
           if (clazz != null) {
               return clazz;
           }
       }
 
       if (dexElementsSuppressedExceptions != null) {
           suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
       }
       return null;
   }
public Class<?> findClass(String name, List<Throwable> suppressed) {
       for (Element element : dexElements) {
           Class<?> clazz = element.findClass(name, definingContext, suppressed);
           if (clazz != null) {
               return clazz;
           }
       }
 
       if (dexElementsSuppressedExceptions != null) {
           suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
       }
       return null;
   }
public Class<?> findClass(String name, ClassLoader definingContext,
              List<Throwable> suppressed) {
          return dexFile != null ? dexFile.loadClassBinaryName(name, definingContext, suppressed)
                  : null;
      }
public Class<?> findClass(String name, ClassLoader definingContext,
              List<Throwable> suppressed) {
          return dexFile != null ? dexFile.loadClassBinaryName(name, definingContext, suppressed)
                  : null;
      }
public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) {
       return defineClass(name, loader, mCookie, this, suppressed);
   }
public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) {
       return defineClass(name, loader, mCookie, this, suppressed);
   }
private static Class defineClass(String name, ClassLoader loader, Object cookie,
                                 DexFile dexFile, List<Throwable> suppressed) {
    Class result = null;
    try {
        result = defineClassNative(name, loader, cookie, dexFile);
    } catch (NoClassDefFoundError e) {
        if (suppressed != null) {
            suppressed.add(e);
        }
    } catch (ClassNotFoundException e) {
        if (suppressed != null) {
            suppressed.add(e);
        }
    }
    return result;
}
private static Class defineClass(String name, ClassLoader loader, Object cookie,
                                 DexFile dexFile, List<Throwable> suppressed) {
    Class result = null;
    try {
        result = defineClassNative(name, loader, cookie, dexFile);
    } catch (NoClassDefFoundError e) {
        if (suppressed != null) {
            suppressed.add(e);
        }
    } catch (ClassNotFoundException e) {
        if (suppressed != null) {
            suppressed.add(e);
        }
    }
    return result;
}
static jclass DexFile_defineClassNative(JNIEnv* env,jclass,jstring javaName,jobject javaLoader,                                        jobject cookie,jobject dexFile) {
...
  for (auto& dex_file : dex_files) {
    const DexFile::ClassDef* dex_class_def =
        OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash);
    if (dex_class_def != nullptr) {
      ScopedObjectAccess soa(env);
      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
      StackHandleScope<1> hs(soa.Self());
      Handle<mirror::ClassLoader> class_loader(
          hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
      ObjPtr<mirror::DexCache> dex_cache =
          class_linker->RegisterDexFile(*dex_file, class_loader.Get());
      if (dex_cache == nullptr) {
        // OOME or InternalError (dexFile already registered with a different class loader).
        soa.Self()->AssertPendingException();
        return nullptr;
      }
      ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(),descriptor.c_str(),hash,class_loader,*dex_file,*dex_class_def);
      // Add the used dex file. This only required for the DexFile.loadClass API since normal
      // class loaders already keep their dex files live.
      class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile),class_loader.Get());
      if (result != nullptr) {
        VLOG(class_linker) << "DexFile_defineClassNative returning " << result
                           << " for " << class_name.c_str();
        return soa.AddLocalReference<jclass>(result);
      }
    }
  }
  VLOG(class_linker) << "Failed to find dex_class_def " << class_name.c_str();
  return nullptr;
}
static jclass DexFile_defineClassNative(JNIEnv* env,jclass,jstring javaName,jobject javaLoader,                                        jobject cookie,jobject dexFile) {
...
  for (auto& dex_file : dex_files) {
    const DexFile::ClassDef* dex_class_def =
        OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash);
    if (dex_class_def != nullptr) {
      ScopedObjectAccess soa(env);
      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
      StackHandleScope<1> hs(soa.Self());
      Handle<mirror::ClassLoader> class_loader(
          hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
      ObjPtr<mirror::DexCache> dex_cache =
          class_linker->RegisterDexFile(*dex_file, class_loader.Get());
      if (dex_cache == nullptr) {
        // OOME or InternalError (dexFile already registered with a different class loader).
        soa.Self()->AssertPendingException();
        return nullptr;
      }
      ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(),descriptor.c_str(),hash,class_loader,*dex_file,*dex_class_def);
      // Add the used dex file. This only required for the DexFile.loadClass API since normal
      // class loaders already keep their dex files live.
      class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile),class_loader.Get());
      if (result != nullptr) {
        VLOG(class_linker) << "DexFile_defineClassNative returning " << result
                           << " for " << class_name.c_str();
        return soa.AddLocalReference<jclass>(result);
      }
    }
  }
  VLOG(class_linker) << "Failed to find dex_class_def " << class_name.c_str();
  return nullptr;
}
mirror::Class* ClassLinker::DefineClass(Thread* self,const char* escriptor,size_t hash,Handle<mirrr::ClassLoader> class_loader,const DexFile& dex_file,const DexFile::ClassDef dex_class_def) {
...
klass->SetDexCache(dex_cache);
SetupClass(*new_dex_file, *new_class_def, klass, class_loader.Get());
...
  // Load the fields and other things after we arenserted in the table. This is so that we don't
  // end up allocating unfree-able linear alloc rources and then lose the race condition. The
  // other reason is that the field roots are onlvisited from the class table. So we need to be
  // inserted before we allocate / fill in these field
  LoadClass(self, *new_dex_file, *new_class_def, klass);
...
if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) {
    // Linking failed.
    if (!klass->IsErroneous()) {
      mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
    }
    return nullptr;
  }
...
mirror::Class* ClassLinker::DefineClass(Thread* self,const char* escriptor,size_t hash,Handle<mirrr::ClassLoader> class_loader,const DexFile& dex_file,const DexFile::ClassDef dex_class_def) {
...
klass->SetDexCache(dex_cache);
SetupClass(*new_dex_file, *new_class_def, klass, class_loader.Get());
...
  // Load the fields and other things after we arenserted in the table. This is so that we don't
  // end up allocating unfree-able linear alloc rources and then lose the race condition. The
  // other reason is that the field roots are onlvisited from the class table. So we need to be
  // inserted before we allocate / fill in these field
  LoadClass(self, *new_dex_file, *new_class_def, klass);
...
if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) {
    // Linking failed.
    if (!klass->IsErroneous()) {
      mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorUnresolved, self);
    }
    return nullptr;
  }
...
void ClassLinker::LoadClass(Thread* self,
                            const DexFile& dex_file,
                            const DexFile::ClassDef& dex_class_def,
                            Handle<mirror::Class> klass) {
  const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
  if (class_data == nullptr) {
    return// no fields or methods - for example a marker interface
  }
  LoadClassMembers(self, dex_file, class_data, klass);
}
void ClassLinker::LoadClass(Thread* self,
                            const DexFile& dex_file,
                            const DexFile::ClassDef& dex_class_def,
                            Handle<mirror::Class> klass) {
  const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
  if (class_data == nullptr) {
    return// no fields or methods - for example a marker interface
  }
  LoadClassMembers(self, dex_file, class_data, klass);
}
void ClassLinker::LoadClassMembers(Thread* self,const DexFile& dex_file,const uint8_t* class_data,Handle<mirror::Class> klass) {
  {    // Note: We cannot have thread suspension until the field and method arrays are setup or else
    // Class::VisitFieldRoots may miss some fields or methods.
    ScopedAssertNoThreadSuspension nts(__FUNCTION__);
    // Load static fields.
...
    for (; it.HasNextStaticField(); it.Next()) {
      uint32_t field_idx = it.GetMemberIndex();
      DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.
      if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
        DCHECK_LT(num_sfields, it.NumStaticFields());
        LoadField(it, klass, &sfields->At(num_sfields));
        ++num_sfields;
        last_field_idx = field_idx;
      }
    }
    // Load instance fields.
    LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,allocator,it.NumInstanceFields());
    size_t num_ifields = 0u;
    last_field_idx = 0u;
    for (; it.HasNextInstanceField(); it.Next()) {
      uint32_t field_idx = it.GetMemberIndex();
      DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.
      if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
        DCHECK_LT(num_ifields, it.NumInstanceFields());
        LoadField(it, klass, &ifields->At(num_ifields));
        ++num_ifields;
        last_field_idx = field_idx;
      }
    }
...
    // Set the field arrays.
    klass->SetSFieldsPtr(sfields);
    DCHECK_EQ(klass->NumStaticFields(), num_sfields);
    klass->SetIFieldsPtr(ifields);
    DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
    // Load methods.
    bool has_oat_class = false;
    const OatFile::OatClass oat_class =
        (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
            ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
            : OatFile::OatClass::Invalid();
    const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
    klass->SetMethodsPtr(
        AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
        it.NumDirectMethods(),
        it.NumVirtualMethods());
    size_t class_def_method_index = 0;
    uint32_t last_dex_method_index = DexFile::kDexNoIndex;
    size_t last_class_def_method_index = 0;
    // TODO These should really use the iterators.
    for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
      ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
      LoadMethod(dex_file, it, klass, method);
      LinkCode(this, method, oat_class_ptr, class_def_method_index);
      uint32_t it_method_index = it.GetMemberIndex();
      if (last_dex_method_index == it_method_index) {
        // duplicate case
        method->SetMethodIndex(last_class_def_method_index);
      } else {
        method->SetMethodIndex(class_def_method_index);
        last_dex_method_index = it_method_index;
        last_class_def_method_index = class_def_method_index;
      }
      class_def_method_index++;
    }
    for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
      ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
      LoadMethod(dex_file, it, klass, method);
      DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
      LinkCode(this, method, oat_class_ptr, class_def_method_index);
      class_def_method_index++;
    }
    DCHECK(!it.HasNext());
  }
  // Ensure that the card is marked so that remembered sets pick up native roots.
  Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
  self->AllowThreadSuspension();
}
void ClassLinker::LoadClassMembers(Thread* self,const DexFile& dex_file,const uint8_t* class_data,Handle<mirror::Class> klass) {
  {    // Note: We cannot have thread suspension until the field and method arrays are setup or else
    // Class::VisitFieldRoots may miss some fields or methods.
    ScopedAssertNoThreadSuspension nts(__FUNCTION__);
    // Load static fields.
...
    for (; it.HasNextStaticField(); it.Next()) {
      uint32_t field_idx = it.GetMemberIndex();
      DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.
      if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
        DCHECK_LT(num_sfields, it.NumStaticFields());
        LoadField(it, klass, &sfields->At(num_sfields));
        ++num_sfields;
        last_field_idx = field_idx;
      }
    }
    // Load instance fields.
    LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,allocator,it.NumInstanceFields());
    size_t num_ifields = 0u;
    last_field_idx = 0u;
    for (; it.HasNextInstanceField(); it.Next()) {
      uint32_t field_idx = it.GetMemberIndex();
      DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.
      if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
        DCHECK_LT(num_ifields, it.NumInstanceFields());
        LoadField(it, klass, &ifields->At(num_ifields));
        ++num_ifields;
        last_field_idx = field_idx;
      }
    }
...
    // Set the field arrays.
    klass->SetSFieldsPtr(sfields);
    DCHECK_EQ(klass->NumStaticFields(), num_sfields);
    klass->SetIFieldsPtr(ifields);
    DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
    // Load methods.
    bool has_oat_class = false;
    const OatFile::OatClass oat_class =
        (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
            ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
            : OatFile::OatClass::Invalid();
    const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
    klass->SetMethodsPtr(
        AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
        it.NumDirectMethods(),
        it.NumVirtualMethods());
    size_t class_def_method_index = 0;
    uint32_t last_dex_method_index = DexFile::kDexNoIndex;
    size_t last_class_def_method_index = 0;
    // TODO These should really use the iterators.
    for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
      ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
      LoadMethod(dex_file, it, klass, method);
      LinkCode(this, method, oat_class_ptr, class_def_method_index);
      uint32_t it_method_index = it.GetMemberIndex();
      if (last_dex_method_index == it_method_index) {
        // duplicate case
        method->SetMethodIndex(last_class_def_method_index);
      } else {
        method->SetMethodIndex(class_def_method_index);
        last_dex_method_index = it_method_index;
        last_class_def_method_index = class_def_method_index;
      }
      class_def_method_index++;
    }
    for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
      ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
      LoadMethod(dex_file, it, klass, method);
      DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
      LinkCode(this, method, oat_class_ptr, class_def_method_index);
      class_def_method_index++;
    }
    DCHECK(!it.HasNext());
  }
  // Ensure that the card is marked so that remembered sets pick up native roots.
  Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
  self->AllowThreadSuspension();
}
void ClassLinker::LoadMethod(const DexFile& dex_file,const ClassDataItemIterator& it,Handle<mirror::Class> klass,ArtMethod* dst) {
  uint32_t dex_method_idx = it.GetMemberIndex();
  const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
  const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
 
  ScopedAssertNoThreadSuspension ants("LoadMethod");
  dst->SetDexMethodIndex(dex_method_idx);
  dst->SetDeclaringClass(klass.Get());
  dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
 
  dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods(), image_pointer_size_);
 
  uint32_t access_flags = it.GetMethodAccessFlags();
 
  if (UNLIKELY(strcmp("finalize", method_name) == 0)) { 
  } else if (method_name[0] == '<') {
    // Fix broken access flags for initializers. Bug 11157540.
    bool is_init = (strcmp("<init>", method_name) == 0);
    bool is_clinit = !is_init && (strcmp("<clinit>", method_name) == 0);
    if (UNLIKELY(!is_init && !is_clinit)) {
      LOG(WARNING) << "Unexpected '<' at start of method name " << method_name;
    } else{
    ...
}
  }
  dst->SetAccessFlags(access_flags);
}
void ClassLinker::LoadMethod(const DexFile& dex_file,const ClassDataItemIterator& it,Handle<mirror::Class> klass,ArtMethod* dst) {
  uint32_t dex_method_idx = it.GetMemberIndex();
  const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
  const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
 
  ScopedAssertNoThreadSuspension ants("LoadMethod");
  dst->SetDexMethodIndex(dex_method_idx);
  dst->SetDeclaringClass(klass.Get());
  dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
 
  dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods(), image_pointer_size_);
 
  uint32_t access_flags = it.GetMethodAccessFlags();
 
  if (UNLIKELY(strcmp("finalize", method_name) == 0)) { 
  } else if (method_name[0] == '<') {
    // Fix broken access flags for initializers. Bug 11157540.
    bool is_init = (strcmp("<init>", method_name) == 0);
    bool is_clinit = !is_init && (strcmp("<clinit>", method_name) == 0);
    if (UNLIKELY(!is_init && !is_clinit)) {
      LOG(WARNING) << "Unexpected '<' at start of method name " << method_name;
    } else{
    ...
}
  }
  dst->SetAccessFlags(access_flags);
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2024-6-12 18:07 被mb_edqxbbqv编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (2)
雪    币: 244
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
能把案例给下吗?
2024-8-19 12:01
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
新鲜的,牛
2024-8-22 18:56
0
游客
登录 | 注册 方可回帖
返回
//