Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/runtime/oat/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 9 kB image not shown  

Quelle  oat_file_test.cc

  Sprache: C
 

/*
 * Copyright (C) 2015 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 "oat_file.h"

#include <dlfcn.h>

#include <algorithm>
#include <cstring>
#include <memory>
#include <string>
#include <string_view>

#include "android-base/scopeguard.h"
#include "base/file_utils.h"
#include "base/os.h"
#include "common_runtime_test.h"
#include "dexopt_test.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "scoped_thread_state_change-inl.h"
#include "vdex_file.h"

namespace art HIDDEN {

using ::testing::HasSubstr;

using std::string_view_literals::operator""sv;

// Returns the offset of the first dex file in the vdex file.
static void GetFirstDexFileOffset(const std::string& vdex_filename, /*out*/ size_t* offset) {
  std::string error_msg;
  std::unique_ptr<VdexFile> vdex_file =
      VdexFile::Open(vdex_filename, /*low_4gb=*/false, &error_msg);
  ASSERT_NE(vdex_file, nullptr) << error_msg;
  const uint8_t* ptr = vdex_file->GetNextDexFileData(/*cursor=*/nullptr, /*dex_file_index=*/0);
  ASSERT_NE(ptr, nullptr) << "No dex code in vdex";
  ASSERT_GE(ptr, vdex_file->Begin());
  ASSERT_LT(ptr, vdex_file->End());
  *offset = ptr - vdex_file->Begin();
}

class OatFileTest : public DexoptTest {};

TEST_F(OatFileTest, LoadOat) {
  std::string dex_location = GetScratchDir() + "/LoadOat.jar";

  Copy(GetDexSrc1(), dex_location);
  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);

  std::string oat_location;
  std::string error_msg;
  ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
      dex_location, kRuntimeISA, &oat_location, &error_msg))
      << error_msg;
  std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
                                                   oat_location,
                                                   oat_location,
                                                   /*executable=*/false,
                                                   /*low_4gb=*/false,
                                                   dex_location,
                                                   &error_msg));
  ASSERT_TRUE(odex_file.get() != nullptr);
}

TEST_F(OatFileTest, ChangingMultiDexUncompressed) {
  std::string dex_location = GetScratchDir() + "/MultiDexUncompressedAligned.jar";

  Copy(GetTestDexFileName("MultiDexUncompressedAligned"), dex_location);
  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kVerify);

  std::string oat_location;
  std::string error_msg;
  ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
      dex_location, kRuntimeISA, &oat_location, &error_msg))
      << error_msg;

  // Ensure we can load that file. Just a precondition.
  {
    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
                                                     oat_location,
                                                     oat_location,
                                                     /*executable=*/false,
                                                     /*low_4gb=*/false,
                                                     dex_location,
                                                     &error_msg));
    ASSERT_TRUE(odex_file != nullptr);
    ASSERT_EQ(2u, odex_file->GetOatDexFiles().size());
  }

  // Now replace the source.
  Copy(GetTestDexFileName("MainUncompressedAligned"), dex_location);

  // And try to load again.
  std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
                                                   oat_location,
                                                   oat_location,
                                                   /*executable=*/false,
                                                   /*low_4gb=*/false,
                                                   dex_location,
                                                   &error_msg));
  EXPECT_TRUE(odex_file == nullptr);
  EXPECT_NE(std::string::npos, error_msg.find("expected 2 uncompressed dex files, but found 1"))
      << error_msg;
}

TEST_F(OatFileTest, DlOpenLoad) {
  std::string dex_location = GetScratchDir() + "/LoadOat.jar";

  Copy(GetDexSrc1(), dex_location);
  GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);

  std::string oat_location;
  std::string error_msg;
  ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
      dex_location, kRuntimeISA, &oat_location, &error_msg))
      << error_msg;

  // Clear previous errors if any.
  dlerror();
  error_msg.clear();
  std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
                                                   oat_location,
                                                   oat_location,
                                                   /*executable=*/true,
                                                   /*low_4gb=*/false,
                                                   dex_location,
                                                   &error_msg));
  ASSERT_NE(odex_file.get(), nullptr) << error_msg;

#ifdef __GLIBC__
  if (!error_msg.empty()) {
    // If a valid oat file was returned but there was an error message, then dlopen failed
    // but the backup ART ELF loader successfully loaded the oat file.
    // There are a few expected reasons for this:
    //   - a bug in glibc that prevents loading dynamic shared objects with a read-only dynamic
    //     section https://sourceware.org/bugzilla/show_bug.cgi?id=28340.
    //   - glibc >= 2.41 fails to dlopen shared objects that don't have GNU_STACK segment,
    //     see https://lists.gnu.org/archive/html/info-gnu/2025-01/msg00014.html
    ASSERT_TRUE(
        error_msg == "DlOpen does not support read-only .dynamic section." ||
        error_msg ==
            "Failed to dlopen '" + oat_location + "': " + oat_location +
                ": cannot enable executable stack as shared object requires: Invalid argument")
        << error_msg;
    GTEST_SKIP() << error_msg;
  }
#else
  // If a valid oat file was returned with no error message, then dlopen was successful.
  ASSERT_TRUE(error_msg.empty()) << error_msg;
#endif

  const char *dlerror_msg = dlerror();
  ASSERT_EQ(dlerror_msg, nullptr) << dlerror_msg;

  // Ensure that the oat file is loaded with dlopen by requesting information about it
  // using dladdr.
  Dl_info info;
  ASSERT_NE(dladdr(odex_file->Begin(), &info), 0);
  EXPECT_STREQ(info.dli_fname, oat_location.c_str())
      << "dli_fname: " << info.dli_fname
      << ", location: " << oat_location;
  EXPECT_STREQ(info.dli_sname, "oatdata") << info.dli_sname;
}

TEST_F(OatFileTest, RejectsCdex) {
  std::string dex_location = GetScratchDir() + "/LoadOat.jar";
  std::string odex_location = GetScratchDir() + "/LoadOat.odex";
  std::string vdex_location = GetVdexFilename(odex_location);

  Copy(GetDexSrc1(), dex_location);
  ASSERT_NO_FATAL_FAILURE(GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed));

  // Patch the generated vdex file to simulate that it contains cdex.
  {
    size_t dex_offset;
    ASSERT_NO_FATAL_FAILURE(GetFirstDexFileOffset(vdex_location, &dex_offset));
    std::unique_ptr<File> vdex_file(OS::OpenFileReadWrite(vdex_location.c_str()));
    ASSERT_NE(vdex_file, nullptr) << strerror(errno);
    auto cleanup = android::base::make_scope_guard([&] { (void)vdex_file->FlushClose(); });
    constexpr std::string_view kCdexMagic = "cdex001\0"sv;
    ASSERT_LE(dex_offset + kCdexMagic.size(), vdex_file->GetLength()) << "Dex file too short";
    bool success = vdex_file->PwriteFully(kCdexMagic.data(), kCdexMagic.size(), dex_offset);
    ASSERT_TRUE(success) << strerror(errno);
    cleanup.Disable();
    ASSERT_EQ(vdex_file->FlushClose(), 0);
  }

  // Create `OatFile` from the vdex file together with the oat file. This should fail.
  {
    std::string error_msg;
    std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
                                                     odex_location,
                                                     odex_location,
                                                     /*executable=*/false,
                                                     /*low_4gb=*/false,
                                                     dex_location,
                                                     &error_msg));
    EXPECT_EQ(odex_file, nullptr) << "Cdex accepted unexpectedly";
    EXPECT_THAT(error_msg, HasSubstr("invalid dex file magic"));
  }

  // Create `OatFile` from the vdex file alone. This should fail too.
  {
    std::string error_msg;
    std::unique_ptr<VdexFile> vdex_file =
        VdexFile::Open(vdex_location, /*low_4gb=*/false, &error_msg);
    ASSERT_NE(vdex_file, nullptr);
    std::unique_ptr<OatFile> odex_file(OatFile::OpenFromVdex(/*zip_fd=*/-1,
                                                             std::move(vdex_file),
                                                             vdex_location,
                                                             /*context=*/nullptr,
                                                             kReasonVdex,
                                                             &error_msg));
    EXPECT_EQ(odex_file, nullptr) << "Cdex accepted unexpectedly";
    EXPECT_THAT(error_msg, HasSubstr("found dex file with invalid dex file version"));
  }
}

}  // namespace art

Messung V0.5 in Prozent
C=88 H=95 G=91

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.