【Android 逆向】ART 脱壳 ( dex2oat 脱壳 | /art/dex2oat/dex2oat.cc#Dex2oat 函数源码 )(二)

简介: 【Android 逆向】ART 脱壳 ( dex2oat 脱壳 | /art/dex2oat/dex2oat.cc#Dex2oat 函数源码 )(二)

/art/dex2oat/dex2oat.cc#Setup 函数源码 :


// 设置编译环境。包括启动运行时和加载/打开引导类路径。
dex2oat::ReturnCode Setup() {
  TimingLogger::ScopedTiming t("dex2oat Setup", timings_);
  if (!PrepareImageClasses() || !PrepareCompiledClasses() || !PrepareCompiledMethods()) {
    return dex2oat::ReturnCode::kOther;
  }
  verification_results_.reset(new VerificationResults(compiler_options_.get()));
  callbacks_.reset(new QuickCompilerCallbacks(
      verification_results_.get(),
      IsBootImage() ?
          CompilerCallbacks::CallbackMode::kCompileBootImage :
          CompilerCallbacks::CallbackMode::kCompileApp));
  RuntimeArgumentMap runtime_options;
  if (!PrepareRuntimeOptions(&runtime_options)) {
    return dex2oat::ReturnCode::kOther;
  }
  CreateOatWriters();
  if (!AddDexFileSources()) {
    return dex2oat::ReturnCode::kOther;
  }
  if (IsBootImage() && image_filenames_.size() > 1) {
  // 如果我们正在编译引导映像,请将引导类路径存储到键值存储中。
  // 我们需要这个多图像的情况。
    key_value_store_->Put(OatHeader::kBootClassPathKey,
                          gc::space::ImageSpace::GetMultiImageBootClassPath(dex_locations_,
                                                                            oat_filenames_,
                                                                            image_filenames_));
  }
  if (!IsBootImage()) {
    // 编译应用程序时,尽早创建运行时以检索oat头所需的映像位置键。
    if (!CreateRuntime(std::move(runtime_options))) {
      return dex2oat::ReturnCode::kCreateRuntime;
    }
    if (CompilerFilter::DependsOnImageChecksum(compiler_options_->GetCompilerFilter())) {
      TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
      std::vector<gc::space::ImageSpace*> image_spaces =
          Runtime::Current()->GetHeap()->GetBootImageSpaces();
      image_file_location_oat_checksum_ = image_spaces[0]->GetImageHeader().GetOatChecksum();
      image_file_location_oat_data_begin_ =
          reinterpret_cast<uintptr_t>(image_spaces[0]->GetImageHeader().GetOatDataBegin());
      image_patch_delta_ = image_spaces[0]->GetImageHeader().GetPatchDelta();
      // Store the boot image filename(s).
      std::vector<std::string> image_filenames;
      for (const gc::space::ImageSpace* image_space : image_spaces) {
        image_filenames.push_back(image_space->GetImageFilename());
      }
      std::string image_file_location = android::base::Join(image_filenames, ':');
      if (!image_file_location.empty()) {
        key_value_store_->Put(OatHeader::kImageLocationKey, image_file_location);
      }
    } else {
      image_file_location_oat_checksum_ = 0u;
      image_file_location_oat_data_begin_ = 0u;
      image_patch_delta_ = 0;
    }
    // Open dex files for class path.
    std::vector<std::string> class_path_locations =
        GetClassPathLocations(runtime_->GetClassPathString());
    OpenClassPathFiles(class_path_locations,
                       &class_path_files_,
                       &opened_oat_files_,
                       runtime_->GetInstructionSet(),
                       classpath_dir_);
    // Store the classpath we have right now.
    std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(class_path_files_);
    std::string encoded_class_path;
    if (class_path_locations.size() == 1 &&
        class_path_locations[0] == OatFile::kSpecialSharedLibrary) {
      // When passing the special shared library as the classpath, it is the only path.
      encoded_class_path = OatFile::kSpecialSharedLibrary;
    } else {
      encoded_class_path = OatFile::EncodeDexFileDependencies(class_path_files, classpath_dir_);
    }
    key_value_store_->Put(OatHeader::kClassPathKey, encoded_class_path);
  }
  // 现在我们已经完成了key\u value\u store\u,开始编写oat文件。
  {
    TimingLogger::ScopedTiming t_dex("Writing and opening dex files", timings_);
    rodata_.reserve(oat_writers_.size());
    for (size_t i = 0, size = oat_writers_.size(); i != size; ++i) {
      rodata_.push_back(elf_writers_[i]->StartRoData());
      // 直接将dex文件解压或复制到oat文件。
      std::unique_ptr<MemMap> opened_dex_files_map;
      std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
   // 无需验证以下各项的dex文件:
   // 1)Dexlayout,因为它进行了验证。也可能无法通过验证,因为
   // 我们不更新dex校验和。
   // 2)当我们有一个vdex文件,这意味着它已经被验证。
      const bool verify = !DoDexLayoutOptimizations() && (input_vdex_file_ == nullptr);
      if (!oat_writers_[i]->WriteAndOpenDexFiles(
          kIsVdexEnabled ? vdex_files_[i].get() : oat_files_[i].get(),
          rodata_.back(),
          instruction_set_,
          instruction_set_features_.get(),
          key_value_store_.get(),
          verify,
          update_input_vdex_,
          &opened_dex_files_map,
          &opened_dex_files)) {
        return dex2oat::ReturnCode::kOther;
      }
      dex_files_per_oat_file_.push_back(MakeNonOwningPointerVector(opened_dex_files));
      if (opened_dex_files_map != nullptr) {
        opened_dex_files_maps_.push_back(std::move(opened_dex_files_map));
        for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
          dex_file_oat_index_map_.emplace(dex_file.get(), i);
          opened_dex_files_.push_back(std::move(dex_file));
        }
      } else {
        DCHECK(opened_dex_files.empty());
      }
    }
  }
  dex_files_ = MakeNonOwningPointerVector(opened_dex_files_);
  // 我们不得不将互换决定推迟到现在,因为这是我们真正需要的时候
  // 了解我们将要使用的dex文件。
  // 确保我们还没有创建驱动程序。
  CHECK(driver_ == nullptr);
  // 如果我们使用交换文件,请确保我们高于阈值以使其成为必要。
  if (swap_fd_ != -1) {
    if (!UseSwap(IsBootImage(), dex_files_)) {
      close(swap_fd_);
      swap_fd_ = -1;
      VLOG(compiler) << "Decided to run without swap.";
    } else {
      LOG(INFO) << "Large app, accepted running with swap.";
    }
  }
  // 请注意,dex2oat不会关闭 swap_fd_。编译器驱动程序的交换空间可以做到这一点。
  // 如果由于大小原因需要降级编译器筛选器,请立即执行该检查。
  if (!IsBootImage() && IsVeryLarge(dex_files_)) {
    if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract,
                                    compiler_options_->GetCompilerFilter())) {
      LOG(INFO) << "Very large app, downgrading to extract.";
   // 注意:这个更改不会反映在键值存储中,这是必须的
   // 在加载dex文件之前完成。当前需要此设置
   // 从DexFile对象获取大小。
   // TODO:重构。b/29790079
      compiler_options_->SetCompilerFilter(CompilerFilter::kExtract);
    }
  }
  if (IsBootImage()) {
    // 对于启动映像,将打开的dex文件传递给运行时::Create()。
    // 注意:运行时获得这些dex文件的所有权。
    runtime_options.Set(RuntimeArgumentMap::BootClassPathDexList, &opened_dex_files_);
    if (!CreateRuntime(std::move(runtime_options))) {
      return dex2oat::ReturnCode::kOther;
    }
  }
  // 如果我们正在处理映像,请重写编译器过滤器以强制进行完整编译。必须是
  // 在导致验证的WellKnownClasses::Init之前完成。注意:不强制
  // 类初始值设定项的编译。
  // 当我们在本机中时,请抓住机会初始化众所周知的类。
  Thread* self = Thread::Current();
  WellKnownClasses::Init(self->GetJniEnv());
  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
  if (!IsBootImage()) {
    constexpr bool kSaveDexInput = false;
    if (kSaveDexInput) {
      SaveDexInput();
    }
    // 句柄和类加载器的创建需要在Runtime::Create之后进行。
    ScopedObjectAccess soa(self);
    // 类路径:首先是给定的类路径。
    std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(class_path_files_);
    // 然后我们将编译dex文件。因此,我们将首先解析类路径。
    class_path_files.insert(class_path_files.end(), dex_files_.begin(), dex_files_.end());
    class_loader_ = class_linker->CreatePathClassLoader(self, class_path_files);
  }
  // 确保打开的dex文件对于dex到dex转换是可写的。
  for (const std::unique_ptr<MemMap>& map : opened_dex_files_maps_) {
    if (!map->Protect(PROT_READ | PROT_WRITE)) {
      PLOG(ERROR) << "Failed to make .dex files writeable.";
      return dex2oat::ReturnCode::kOther;
    }
  }
  // 确保dex缓存保持活动状态,因为我们不希望在编译期间发生类卸载。
  for (const auto& dex_file : dex_files_) {
    ScopedObjectAccess soa(self);
    dex_caches_.push_back(soa.AddLocalReference<jobject>(
        class_linker->RegisterDexFile(*dex_file,
                                      soa.Decode<mirror::ClassLoader>(class_loader_).Ptr())));
    if (dex_caches_.back() == nullptr) {
      soa.Self()->AssertPendingException();
      soa.Self()->ClearException();
      PLOG(ERROR) << "Failed to register dex file.";
      return dex2oat::ReturnCode::kOther;
    }
    // 预注册dex文件,以便在编译和验证期间无需锁定即可访问验证结果。
    verification_results_->AddDexFile(dex_file);
  }
  return dex2oat::ReturnCode::kNoFailure;
}


源码路径 : /art/dex2oat/dex2oat.cc#Setup


目录
相关文章
|
10月前
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
613 2
|
Ubuntu 开发工具 Android开发
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
本文介绍了在基于Ubuntu 22.04的环境下配置Python 3.9、安装repo工具、下载和同步AOSP源码包以及处理repo同步错误的详细步骤。
1534 0
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
|
11月前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
存储 Java 编译器
🔍深入Android底层,揭秘JVM与ART的奥秘,性能优化新视角!🔬
【9月更文挑战第12天】在Android开发领域,深入了解其底层机制对提升应用性能至关重要。本文详述了从早期Dalvik虚拟机到现今Android Runtime(ART)的演变过程,揭示了ART通过预编译技术实现更快启动速度和更高执行效率的奥秘。文中还介绍了ART的编译器与运行时环境,并提出了减少DEX文件数量、优化代码结构及合理管理内存等多种性能优化策略。通过掌握这些知识,开发者可以从全新的角度提升应用性能。
450 11
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
722 1
|
开发工具 uml git
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
本文分享了下载AOSP源码的方法,包括如何使用repo工具和处理常见的repo sync错误,以及配置Python环境以确保顺利同步特定版本的AOSP代码。
2894 0
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
1463 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
|
Android开发
我的Android 进阶修炼(1): AOSP源码根目录结构
本文介绍了AOSP源码的根目录结构,提供了基于MTK9269 Android 9.0源码的目录说明,帮助读者了解AOSP源码的组织方式和各目录的功能。
1283 0
我的Android 进阶修炼(1): AOSP源码根目录结构
|
开发工具 Android开发 git
全志H713 Android 11 :给AOSP源码,新增一个Product
本文介绍了在全志H713 Android 11平台上新增名为myboard的产品的步骤,包括创建新的device目录、编辑配置文件、新增内核配置、记录差异列表以及编译kernel和Android系统的详细过程。
1346 0
|
Ubuntu 开发工具 Android开发
Repo下载、编译AOSP源码:基于Ubuntu 21.04,android-12.1.0_r27
文章记录了作者在Ubuntu 21.04服务器上配置环境、下载并编译基于Android 12.1.0_r27版本的AOSP源码的过程,包括解决编译过程中遇到的问题和错误处理方法。
1408 0

热门文章

最新文章