summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/optimizing_unit_test.h6
-rw-r--r--dex2oat/dex2oat.cc4
-rw-r--r--libdexfile/dex/art_dex_file_loader.cc110
-rw-r--r--libdexfile/dex/art_dex_file_loader.h10
-rw-r--r--libdexfile/dex/compact_dex_file.cc16
-rw-r--r--libdexfile/dex/compact_dex_file.h9
-rw-r--r--libdexfile/dex/dex_file.cc96
-rw-r--r--libdexfile/dex/dex_file.h87
-rw-r--r--libdexfile/dex/dex_file_loader.cc92
-rw-r--r--libdexfile/dex/dex_file_loader.h10
-rw-r--r--libdexfile/dex/dex_file_verifier_test.cc5
-rw-r--r--libdexfile/dex/standard_dex_file.h12
-rw-r--r--runtime/class_linker.cc5
-rw-r--r--runtime/class_linker.h2
-rw-r--r--runtime/class_linker_test.cc12
-rw-r--r--runtime/common_runtime_test.cc2
-rw-r--r--runtime/gc/collector/concurrent_copying.cc8
-rw-r--r--runtime/native/java_lang_reflect_Constructor.cc11
-rw-r--r--runtime/reflection.cc134
-rw-r--r--runtime/reflection.h8
-rw-r--r--runtime/runtime.cc92
-rw-r--r--runtime/runtime.h2
-rw-r--r--runtime/thread.cc10
-rwxr-xr-xtest/etc/default-build2
-rw-r--r--tools/hiddenapi/hiddenapi.cc302
-rw-r--r--tools/hiddenapi/hiddenapi_test.cc69
26 files changed, 634 insertions, 482 deletions
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index a9bc5664c0..a627f65ed4 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -129,12 +129,10 @@ class OptimizingUnitTestHelper {
// Create the dex file based on the fake data. Call the constructor so that we can use virtual
// functions. Don't use the arena for the StandardDexFile otherwise the dex location leaks.
dex_files_.emplace_back(new StandardDexFile(
- dex_data,
- sizeof(StandardDexFile::Header),
+ std::make_unique<NonOwningDexFileContainer>(dex_data, sizeof(StandardDexFile::Header)),
"no_location",
/*location_checksum*/ 0,
- /*oat_dex_file*/ nullptr,
- /*container*/ nullptr));
+ /*oat_dex_file*/ nullptr));
return new (allocator) HGraph(
allocator,
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index c9eb71d809..8dca889de5 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -2613,11 +2613,11 @@ class Dex2Oat FINAL {
// set up.
interpreter::UnstartedRuntime::Initialize();
- runtime_->GetClassLinker()->RunRootClinits();
+ Thread* self = Thread::Current();
+ runtime_->RunRootClinits(self);
// Runtime::Create acquired the mutator_lock_ that is normally given away when we
// Runtime::Start, give it away now so that we don't starve GC.
- Thread* self = Thread::Current();
self->TransitionFromRunnableToSuspended(kNative);
return true;
diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc
index 392ce1e7f5..05986ecce3 100644
--- a/libdexfile/dex/art_dex_file_loader.cc
+++ b/libdexfile/dex/art_dex_file_loader.cc
@@ -71,6 +71,14 @@ class MemMapContainer : public DexFileContainer {
}
}
+ const uint8_t* Begin() OVERRIDE {
+ return mem_map_->Begin();
+ }
+
+ size_t Size() OVERRIDE {
+ return mem_map_->Size();
+ }
+
private:
std::unique_ptr<MemMap> mem_map_;
DISALLOW_COPY_AND_ASSIGN(MemMapContainer);
@@ -164,17 +172,14 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const uint8_t* base,
bool verify_checksum,
std::string* error_msg) const {
ScopedTrace trace(std::string("Open dex file from RAM ") + location);
- return OpenCommon(base,
- size,
- /*data_base*/ nullptr,
- /*data_size*/ 0u,
+ return OpenCommon(std::make_unique<NonOwningDexFileContainer>(base, size),
+ std::make_unique<EmptyDexFileContainer>(),
location,
location_checksum,
oat_dex_file,
verify,
verify_checksum,
error_msg,
- /*container*/ nullptr,
/*verify_result*/ nullptr);
}
@@ -194,18 +199,16 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const std::string& locatio
return nullptr;
}
- std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
- map->Size(),
- /*data_base*/ nullptr,
- /*data_size*/ 0u,
- location,
- location_checksum,
- kNoOatDexFile,
- verify,
- verify_checksum,
- error_msg,
- std::make_unique<MemMapContainer>(std::move(map)),
- /*verify_result*/ nullptr);
+ std::unique_ptr<DexFile> dex_file =
+ OpenCommon(std::make_unique<MemMapContainer>(std::move(map)),
+ std::make_unique<EmptyDexFileContainer>(),
+ location,
+ location_checksum,
+ kNoOatDexFile,
+ verify,
+ verify_checksum,
+ error_msg,
+ /*verify_result*/ nullptr);
// Opening CompactDex is only supported from vdex files.
if (dex_file != nullptr && dex_file->IsCompactDexFile()) {
*error_msg = StringPrintf("Opening CompactDex file '%s' is only supported from vdex files",
@@ -323,18 +326,16 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::OpenFile(int fd,
const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(map->Begin());
- std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
- map->Size(),
- /*data_base*/ nullptr,
- /*data_size*/ 0u,
- location,
- dex_header->checksum_,
- kNoOatDexFile,
- verify,
- verify_checksum,
- error_msg,
- std::make_unique<MemMapContainer>(std::move(map)),
- /*verify_result*/ nullptr);
+ std::unique_ptr<DexFile> dex_file =
+ OpenCommon(std::make_unique<MemMapContainer>(std::move(map)),
+ std::make_unique<EmptyDexFileContainer>(),
+ location,
+ dex_header->checksum_,
+ kNoOatDexFile,
+ verify,
+ verify_checksum,
+ error_msg,
+ /*verify_result*/ nullptr);
// Opening CompactDex is only supported from vdex files.
if (dex_file != nullptr && dex_file->IsCompactDexFile()) {
@@ -398,18 +399,16 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::OpenOneDexFileFromZip(
return nullptr;
}
VerifyResult verify_result;
- std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
- map->Size(),
- /*data_base*/ nullptr,
- /*data_size*/ 0u,
- location,
- zip_entry->GetCrc32(),
- kNoOatDexFile,
- verify,
- verify_checksum,
- error_msg,
- std::make_unique<MemMapContainer>(std::move(map)),
- &verify_result);
+ std::unique_ptr<DexFile> dex_file =
+ OpenCommon(std::make_unique<MemMapContainer>(std::move(map)),
+ std::make_unique<EmptyDexFileContainer>(),
+ location,
+ zip_entry->GetCrc32(),
+ kNoOatDexFile,
+ verify,
+ verify_checksum,
+ error_msg,
+ &verify_result);
if (dex_file != nullptr && dex_file->IsCompactDexFile()) {
*error_msg = StringPrintf("Opening CompactDex file '%s' is only supported from vdex files",
location.c_str());
@@ -506,29 +505,24 @@ bool ArtDexFileLoader::OpenAllDexFilesFromZip(
}
}
-std::unique_ptr<DexFile> ArtDexFileLoader::OpenCommon(const uint8_t* base,
- size_t size,
- const uint8_t* data_base,
- size_t data_size,
- const std::string& location,
- uint32_t location_checksum,
- const OatDexFile* oat_dex_file,
- bool verify,
- bool verify_checksum,
- std::string* error_msg,
- std::unique_ptr<DexFileContainer> container,
- VerifyResult* verify_result) {
- std::unique_ptr<DexFile> dex_file = DexFileLoader::OpenCommon(base,
- size,
- data_base,
- data_size,
+std::unique_ptr<DexFile> ArtDexFileLoader::OpenCommon(
+ std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
+ const std::string& location,
+ uint32_t location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool verify,
+ bool verify_checksum,
+ std::string* error_msg,
+ VerifyResult* verify_result) {
+ std::unique_ptr<DexFile> dex_file = DexFileLoader::OpenCommon(std::move(main_section),
+ std::move(data_section),
location,
location_checksum,
oat_dex_file,
verify,
verify_checksum,
error_msg,
- std::move(container),
verify_result);
// Check if this dex file is located in the framework directory.
diff --git a/libdexfile/dex/art_dex_file_loader.h b/libdexfile/dex/art_dex_file_loader.h
index a460aee60f..9f92b721a2 100644
--- a/libdexfile/dex/art_dex_file_loader.h
+++ b/libdexfile/dex/art_dex_file_loader.h
@@ -121,17 +121,17 @@ class ArtDexFileLoader : public DexFileLoader {
std::string* error_msg,
ZipOpenErrorCode* error_code) const;
- static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base,
- size_t size,
- const uint8_t* data_base,
- size_t data_size,
+ // main_section points to the header and fixed-sized objects (ids, etc.)
+ // If not empty (Begin != nullptr) data_section points to the dex file's variable-sized
+ // objects such as strings, class_data_items, etc.
+ static std::unique_ptr<DexFile> OpenCommon(std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
bool verify,
bool verify_checksum,
std::string* error_msg,
- std::unique_ptr<DexFileContainer> container,
VerifyResult* verify_result);
};
diff --git a/libdexfile/dex/compact_dex_file.cc b/libdexfile/dex/compact_dex_file.cc
index 302b59ee91..4bd1675423 100644
--- a/libdexfile/dex/compact_dex_file.cc
+++ b/libdexfile/dex/compact_dex_file.cc
@@ -84,22 +84,16 @@ uint32_t CompactDexFile::CalculateChecksum() const {
return CalculateChecksum(Begin(), Size(), DataBegin(), DataSize());
}
-CompactDexFile::CompactDexFile(const uint8_t* base,
- size_t size,
- const uint8_t* data_begin,
- size_t data_size,
+CompactDexFile::CompactDexFile(std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
const std::string& location,
uint32_t location_checksum,
- const OatDexFile* oat_dex_file,
- std::unique_ptr<DexFileContainer> container)
- : DexFile(base,
- size,
- data_begin,
- data_size,
+ const OatDexFile* oat_dex_file)
+ : DexFile(std::move(main_section),
+ std::move(data_section),
location,
location_checksum,
oat_dex_file,
- std::move(container),
/*is_compact_dex*/ true),
debug_info_offsets_(DataBegin() + GetHeader().debug_info_offsets_pos_,
GetHeader().debug_info_base_,
diff --git a/libdexfile/dex/compact_dex_file.h b/libdexfile/dex/compact_dex_file.h
index affc9a20b0..ffaa9a7155 100644
--- a/libdexfile/dex/compact_dex_file.h
+++ b/libdexfile/dex/compact_dex_file.h
@@ -284,14 +284,11 @@ class CompactDexFile : public DexFile {
virtual uint32_t CalculateChecksum() const OVERRIDE;
private:
- CompactDexFile(const uint8_t* base,
- size_t size,
- const uint8_t* data_begin,
- size_t data_size,
+ CompactDexFile(std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
const std::string& location,
uint32_t location_checksum,
- const OatDexFile* oat_dex_file,
- std::unique_ptr<DexFileContainer> container);
+ const OatDexFile* oat_dex_file);
CompactOffsetTable::Accessor debug_info_offsets_;
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index f1f896058c..c2b478aded 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -73,61 +73,101 @@ uint32_t DexFile::ChecksumMemoryRange(const uint8_t* begin, size_t size) {
}
int DexFile::GetPermissions() const {
- CHECK(container_.get() != nullptr);
- return container_->GetPermissions();
+ CHECK(main_section_ != nullptr);
+ return main_section_->GetPermissions();
}
bool DexFile::IsReadOnly() const {
- CHECK(container_.get() != nullptr);
- return container_->IsReadOnly();
+ CHECK(main_section_ != nullptr);
+ return main_section_->IsReadOnly();
}
bool DexFile::EnableWrite() const {
- CHECK(container_.get() != nullptr);
- return container_->EnableWrite();
+ CHECK(main_section_ != nullptr);
+ return main_section_->EnableWrite();
}
bool DexFile::DisableWrite() const {
- CHECK(container_.get() != nullptr);
- return container_->DisableWrite();
+ CHECK(main_section_ != nullptr);
+ return main_section_->DisableWrite();
}
-DexFile::DexFile(const uint8_t* base,
- size_t size,
- const uint8_t* data_begin,
- size_t data_size,
+DexFile::DexFile(std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
- std::unique_ptr<DexFileContainer> container,
bool is_compact_dex)
- : begin_(base),
- size_(size),
- data_begin_(data_begin),
- data_size_(data_size),
+ : main_section_(std::move(main_section)),
location_(location),
location_checksum_(location_checksum),
- header_(reinterpret_cast<const Header*>(base)),
- string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)),
- type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)),
- field_ids_(reinterpret_cast<const FieldId*>(base + header_->field_ids_off_)),
- method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)),
- proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
- class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
+ header_(reinterpret_cast<const Header*>(main_section_->Begin())),
+ string_ids_(reinterpret_cast<const StringId*>(main_section_->Begin() +
+ header_->string_ids_off_)),
+ type_ids_(reinterpret_cast<const TypeId*>(main_section_->Begin() + header_->type_ids_off_)),
+ field_ids_(reinterpret_cast<const FieldId*>(main_section_->Begin() +
+ header_->field_ids_off_)),
+ method_ids_(reinterpret_cast<const MethodId*>(main_section_->Begin() +
+ header_->method_ids_off_)),
+ proto_ids_(reinterpret_cast<const ProtoId*>(main_section_->Begin() +
+ header_->proto_ids_off_)),
+ class_defs_(reinterpret_cast<const ClassDef*>(main_section_->Begin() +
+ header_->class_defs_off_)),
method_handles_(nullptr),
num_method_handles_(0),
call_site_ids_(nullptr),
num_call_site_ids_(0),
oat_dex_file_(oat_dex_file),
- container_(std::move(container)),
is_compact_dex_(is_compact_dex),
is_platform_dex_(false) {
- CHECK(begin_ != nullptr) << GetLocation();
- CHECK_GT(size_, 0U) << GetLocation();
+ CHECK(main_section_->Begin() != nullptr) << GetLocation();
+ CHECK_GT(main_section_->Size(), 0U) << GetLocation();
// Check base (=header) alignment.
// Must be 4-byte aligned to avoid undefined behavior when accessing
// any of the sections via a pointer.
- CHECK_ALIGNED(begin_, alignof(Header));
+ CHECK_ALIGNED(main_section_->Begin(), alignof(Header));
+
+ data_section_ = std::move(data_section);
+
+ InitializeSectionsFromMapList();
+}
+
+DexFile::DexFile(std::unique_ptr<DexFileContainer> main_section,
+ const std::string& location,
+ uint32_t location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool is_compact_dex)
+ : main_section_(std::move(main_section)),
+ location_(location),
+ location_checksum_(location_checksum),
+ header_(reinterpret_cast<const Header*>(main_section_->Begin())),
+ string_ids_(reinterpret_cast<const StringId*>(main_section_->Begin() +
+ header_->string_ids_off_)),
+ type_ids_(reinterpret_cast<const TypeId*>(main_section_->Begin() + header_->type_ids_off_)),
+ field_ids_(reinterpret_cast<const FieldId*>(main_section_->Begin() +
+ header_->field_ids_off_)),
+ method_ids_(reinterpret_cast<const MethodId*>(main_section_->Begin() +
+ header_->method_ids_off_)),
+ proto_ids_(reinterpret_cast<const ProtoId*>(main_section_->Begin() +
+ header_->proto_ids_off_)),
+ class_defs_(reinterpret_cast<const ClassDef*>(main_section_->Begin() +
+ header_->class_defs_off_)),
+ method_handles_(nullptr),
+ num_method_handles_(0),
+ call_site_ids_(nullptr),
+ num_call_site_ids_(0),
+ oat_dex_file_(oat_dex_file),
+ is_compact_dex_(is_compact_dex),
+ is_platform_dex_(false) {
+ CHECK(main_section_->Begin() != nullptr) << GetLocation();
+ CHECK_GT(main_section_->Size(), 0U) << GetLocation();
+ // Check base (=header) alignment.
+ // Must be 4-byte aligned to avoid undefined behavior when accessing
+ // any of the sections via a pointer.
+ CHECK_ALIGNED(main_section_->Begin(), alignof(Header));
+
+ data_section_ = std::make_unique<NonOwningDexFileContainer>(main_section_->Begin(),
+ main_section_->Size());
InitializeSectionsFromMapList();
}
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index 67abdca148..c94c786699 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -56,11 +56,48 @@ class DexFileContainer {
virtual bool IsReadOnly() = 0;
virtual bool EnableWrite() = 0;
virtual bool DisableWrite() = 0;
+ virtual const uint8_t* Begin() = 0;
+ virtual size_t Size() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(DexFileContainer);
};
+class EmptyDexFileContainer FINAL : public DexFileContainer {
+ public:
+ EmptyDexFileContainer() { }
+ ~EmptyDexFileContainer() { }
+
+ int GetPermissions() OVERRIDE { return 0; }
+ bool IsReadOnly() OVERRIDE { return true; }
+ bool EnableWrite() OVERRIDE { return false; }
+ bool DisableWrite() OVERRIDE { return false; }
+ const uint8_t* Begin() OVERRIDE { return nullptr; }
+ size_t Size() OVERRIDE { return 0U; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(EmptyDexFileContainer);
+};
+
+class NonOwningDexFileContainer FINAL : public DexFileContainer {
+ public:
+ NonOwningDexFileContainer(const uint8_t* begin, size_t size) : begin_(begin), size_(size) { }
+ ~NonOwningDexFileContainer() { }
+
+ int GetPermissions() OVERRIDE { return 0; }
+ bool IsReadOnly() OVERRIDE { return true; }
+ bool EnableWrite() OVERRIDE { return false; }
+ bool DisableWrite() OVERRIDE { return false; }
+ const uint8_t* Begin() OVERRIDE { return begin_; }
+ size_t Size() OVERRIDE { return size_; }
+
+ private:
+ const uint8_t* begin_;
+ size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonOwningDexFileContainer);
+};
+
// Dex file is the API that exposes native dex files (ordinary dex files) and CompactDex.
// Originally, the dex file format used by ART was mostly the same as APKs. The only change was
// quickened opcodes and layout optimizations.
@@ -754,7 +791,7 @@ class DexFile {
// Check that the offset is in bounds.
// Note that although the specification says that 0 should be used if there
// is no debug information, some applications incorrectly use 0xFFFFFFFF.
- return (debug_info_off == 0 || debug_info_off >= data_size_)
+ return (debug_info_off == 0 || debug_info_off >= DataSize())
? nullptr
: DataBegin() + debug_info_off;
}
@@ -929,19 +966,19 @@ class DexFile {
bool DisableWrite() const;
const uint8_t* Begin() const {
- return begin_;
+ return main_section_->Begin();
}
size_t Size() const {
- return size_;
+ return main_section_->Size();
}
const uint8_t* DataBegin() const {
- return data_begin_;
+ return data_section_->Begin();
}
size_t DataSize() const {
- return data_size_;
+ return data_section_->Size();
}
template <typename T>
@@ -1009,7 +1046,7 @@ class DexFile {
}
DexFileContainer* GetContainer() const {
- return container_.get();
+ return main_section_.get();
}
// Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags.
@@ -1021,14 +1058,25 @@ class DexFile {
// First Dex format version supporting default methods.
static const uint32_t kDefaultMethodsVersion = 37;
- DexFile(const uint8_t* base,
- size_t size,
- const uint8_t* data_begin,
- size_t data_size,
+ // For the two constructors, some notation needs explanation.
+ // Dex files consist of two sections:
+ // 1) "main" -- contains the header and fixed-sized objects (ids, etc.)
+ // 2) "data" -- contains variable-sized objects such as strings, class_data_items, etc.
+ // For StandardDexFile, both sections are addressed through one pointer.
+ // For CompactDexFile multiple dex files share one data section, but each has its
+ // own main section, and hence we need two pointers.
+
+ DexFile(std::unique_ptr<DexFileContainer> main_section,
+ const std::string& location,
+ uint32_t location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool is_compact_dex);
+
+ DexFile(std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
- std::unique_ptr<DexFileContainer> container,
bool is_compact_dex);
// Top-level initializer that calls other Init methods.
@@ -1040,17 +1088,11 @@ class DexFile {
// Initialize section info for sections only found in map. Returns true on success.
void InitializeSectionsFromMapList();
- // The base address of the memory mapping.
- const uint8_t* const begin_;
-
- // The size of the underlying memory allocation in bytes.
- const size_t size_;
+ // The container for the header and fixed portions.
+ std::unique_ptr<DexFileContainer> main_section_;
- // The base address of the data section (same as Begin() for standard dex).
- const uint8_t* const data_begin_;
-
- // The size of the data section.
- const size_t data_size_;
+ // The container for the data section
+ std::unique_ptr<DexFileContainer> data_section_;
// Typically the dex file name when available, alternatively some identifying string.
//
@@ -1098,9 +1140,6 @@ class DexFile {
// null.
mutable const OatDexFile* oat_dex_file_;
- // Manages the underlying memory allocation.
- std::unique_ptr<DexFileContainer> container_;
-
// If the dex file is a compact dex file. If false then the dex file is a standard dex file.
const bool is_compact_dex_;
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 457addf114..156f655150 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -54,8 +54,17 @@ class VectorContainer : public DexFileContainer {
return false;
}
+ uint8_t* Begin() OVERRIDE {
+ return vector_.data();
+ }
+
+ size_t Size() OVERRIDE {
+ return vector_.size();
+ }
+
private:
std::vector<uint8_t> vector_;
+
DISALLOW_COPY_AND_ASSIGN(VectorContainer);
};
@@ -224,17 +233,14 @@ std::unique_ptr<const DexFile> DexFileLoader::Open(const uint8_t* base,
bool verify,
bool verify_checksum,
std::string* error_msg) const {
- return OpenCommon(base,
- size,
- /*data_base*/ nullptr,
- /*data_size*/ 0,
+ return OpenCommon(std::make_unique<NonOwningDexFileContainer>(base, size),
+ std::make_unique<EmptyDexFileContainer>(),
location,
location_checksum,
oat_dex_file,
verify,
verify_checksum,
error_msg,
- /*container*/ nullptr,
/*verify_result*/ nullptr);
}
@@ -249,17 +255,14 @@ std::unique_ptr<const DexFile> DexFileLoader::OpenWithDataSection(
bool verify,
bool verify_checksum,
std::string* error_msg) const {
- return OpenCommon(base,
- size,
- data_base,
- data_size,
+ return OpenCommon(std::make_unique<NonOwningDexFileContainer>(base, size),
+ std::make_unique<NonOwningDexFileContainer>(data_base, data_size),
location,
location_checksum,
oat_dex_file,
verify,
verify_checksum,
error_msg,
- /*container*/ nullptr,
/*verify_result*/ nullptr);
}
@@ -307,49 +310,47 @@ bool DexFileLoader::OpenAll(
return false;
}
-std::unique_ptr<DexFile> DexFileLoader::OpenCommon(const uint8_t* base,
- size_t size,
- const uint8_t* data_base,
- size_t data_size,
+std::unique_ptr<DexFile> DexFileLoader::OpenCommon(std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
bool verify,
bool verify_checksum,
std::string* error_msg,
- std::unique_ptr<DexFileContainer> container,
VerifyResult* verify_result) {
if (verify_result != nullptr) {
*verify_result = VerifyResult::kVerifyNotAttempted;
}
std::unique_ptr<DexFile> dex_file;
- if (size >= sizeof(StandardDexFile::Header) && StandardDexFile::IsMagicValid(base)) {
- if (data_size != 0) {
- CHECK_EQ(base, data_base) << "Unsupported for standard dex";
+ if (main_section->Size() >= sizeof(StandardDexFile::Header) &&
+ StandardDexFile::IsMagicValid(main_section->Begin())) {
+ if (data_section->Size() != 0) {
+ CHECK_EQ(main_section->Begin(), data_section->Begin()) << "Unsupported for standard dex";
}
- dex_file.reset(new StandardDexFile(base,
- size,
+ CHECK(main_section != nullptr);
+ CHECK(main_section->Begin() != nullptr);
+ dex_file.reset(new StandardDexFile(std::move(main_section),
location,
location_checksum,
- oat_dex_file,
- std::move(container)));
- } else if (size >= sizeof(CompactDexFile::Header) && CompactDexFile::IsMagicValid(base)) {
- if (data_base == nullptr) {
+ oat_dex_file));
+ } else if (main_section->Size() >= sizeof(CompactDexFile::Header) &&
+ CompactDexFile::IsMagicValid(main_section->Begin())) {
+ if (data_section->Begin() == nullptr) {
// TODO: Is there a clean way to support both an explicit data section and reading the one
// from the header.
- CHECK_EQ(data_size, 0u);
- const CompactDexFile::Header* const header = CompactDexFile::Header::At(base);
- data_base = base + header->data_off_;
- data_size = header->data_size_;
+ CHECK_EQ(data_section->Size(), 0u);
+ const CompactDexFile::Header* const header =
+ CompactDexFile::Header::At(main_section->Begin());
+ data_section =
+ std::make_unique<NonOwningDexFileContainer>(main_section->Begin() + header->data_off_,
+ header->data_size_);
}
- dex_file.reset(new CompactDexFile(base,
- size,
- data_base,
- data_size,
+ dex_file.reset(new CompactDexFile(std::move(main_section),
+ std::move(data_section),
location,
location_checksum,
- oat_dex_file,
- std::move(container)));
+ oat_dex_file));
// Disable verification for CompactDex input.
verify = false;
} else {
@@ -409,19 +410,16 @@ std::unique_ptr<const DexFile> DexFileLoader::OpenOneDexFileFromZip(
return nullptr;
}
VerifyResult verify_result;
- std::unique_ptr<const DexFile> dex_file = OpenCommon(
- map.data(),
- map.size(),
- /*data_base*/ nullptr,
- /*data_size*/ 0u,
- location,
- zip_entry->GetCrc32(),
- /*oat_dex_file*/ nullptr,
- verify,
- verify_checksum,
- error_msg,
- std::make_unique<VectorContainer>(std::move(map)),
- &verify_result);
+ std::unique_ptr<const DexFile> dex_file =
+ OpenCommon(std::make_unique<VectorContainer>(std::move(map)),
+ std::make_unique<EmptyDexFileContainer>(),
+ location,
+ zip_entry->GetCrc32(),
+ /*oat_dex_file*/ nullptr,
+ verify,
+ verify_checksum,
+ error_msg,
+ &verify_result);
if (dex_file == nullptr) {
if (verify_result == VerifyResult::kVerifyNotAttempted) {
*error_code = ZipOpenErrorCode::kDexFileError;
diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h
index 01532203eb..0bd6446b7b 100644
--- a/libdexfile/dex/dex_file_loader.h
+++ b/libdexfile/dex/dex_file_loader.h
@@ -161,17 +161,17 @@ class DexFileLoader {
kVerifyFailed
};
- static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base,
- size_t size,
- const uint8_t* data_base,
- size_t data_size,
+ // main_section points to the header and fixed-sized objects (ids, etc.)
+ // If not empty (Begin != nullptr) data_section points to the dex file's variable-sized
+ // objects such as strings, class_data_items, etc.
+ static std::unique_ptr<DexFile> OpenCommon(std::unique_ptr<DexFileContainer> main_section,
+ std::unique_ptr<DexFileContainer> data_section,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
bool verify,
bool verify_checksum,
std::string* error_msg,
- std::unique_ptr<DexFileContainer> container,
VerifyResult* verify_result);
private:
diff --git a/libdexfile/dex/dex_file_verifier_test.cc b/libdexfile/dex/dex_file_verifier_test.cc
index c9bac0fef2..9d9f1bd025 100644
--- a/libdexfile/dex/dex_file_verifier_test.cc
+++ b/libdexfile/dex/dex_file_verifier_test.cc
@@ -56,7 +56,10 @@ static void FixUpChecksum(uint8_t* dex_file) {
class DexFileVerifierTest : public testing::Test {
protected:
DexFile* GetDexFile(const uint8_t* dex_bytes, size_t length) {
- return new StandardDexFile(dex_bytes, length, "tmp", 0, nullptr, nullptr);
+ return new StandardDexFile(std::make_unique<NonOwningDexFileContainer>(dex_bytes, length),
+ "tmp",
+ 0,
+ nullptr);
}
void VerifyModification(const char* dex_file_base64_content,
diff --git a/libdexfile/dex/standard_dex_file.h b/libdexfile/dex/standard_dex_file.h
index 999e5b99e9..0121d6039a 100644
--- a/libdexfile/dex/standard_dex_file.h
+++ b/libdexfile/dex/standard_dex_file.h
@@ -88,20 +88,14 @@ class StandardDexFile : public DexFile {
}
private:
- StandardDexFile(const uint8_t* base,
- size_t size,
+ StandardDexFile(std::unique_ptr<DexFileContainer> container,
const std::string& location,
uint32_t location_checksum,
- const OatDexFile* oat_dex_file,
- std::unique_ptr<DexFileContainer> container)
- : DexFile(base,
- size,
- /*data_begin*/ base,
- /*data_size*/ size,
+ const OatDexFile* oat_dex_file)
+ : DexFile(std::move(container),
location,
location_checksum,
oat_dex_file,
- std::move(container),
/*is_compact_dex*/ false) {}
friend class DexFileLoader;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c219d3dd68..4a5da1f1e9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -864,8 +864,7 @@ void ClassLinker::FinishInit(Thread* self) {
VLOG(startup) << "ClassLinker::FinishInit exiting";
}
-void ClassLinker::RunRootClinits() {
- Thread* self = Thread::Current();
+void ClassLinker::RunRootClinits(Thread* self) {
for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); ++i) {
ObjPtr<mirror::Class> c = GetClassRoot(ClassRoot(i), this);
if (!c->IsArrayClass() && !c->IsPrimitive()) {
@@ -873,6 +872,8 @@ void ClassLinker::RunRootClinits() {
Handle<mirror::Class> h_class(hs.NewHandle(c));
EnsureInitialized(self, h_class, true, true);
self->AssertNoPendingException();
+ } else {
+ DCHECK(c->IsInitialized());
}
}
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 30c242399d..e4d9c96696 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -405,7 +405,7 @@ class ClassLinker {
// Initializes classes that have instances in the image but that have
// <clinit> methods so they could not be initialized by the compiler.
- void RunRootClinits()
+ void RunRootClinits(Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index e40f1dbcdf..2a2aff1002 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -1521,12 +1521,12 @@ TEST_F(ClassLinkerTest, RegisterDexFileName) {
dex_cache->SetLocation(location.Get());
const DexFile* old_dex_file = dex_cache->GetDexFile();
- std::unique_ptr<DexFile> dex_file(new StandardDexFile(old_dex_file->Begin(),
- old_dex_file->Size(),
- location->ToModifiedUtf8(),
- 0u,
- nullptr,
- nullptr));
+ std::unique_ptr<DexFile> dex_file(
+ new StandardDexFile(std::make_unique<NonOwningDexFileContainer>(old_dex_file->Begin(),
+ old_dex_file->Size()),
+ location->ToModifiedUtf8(),
+ 0u,
+ nullptr));
{
WriterMutexLock mu(soa.Self(), *Locks::dex_lock_);
// Check that inserting with a UTF16 name works.
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 75b091d98f..be39631e44 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -182,7 +182,7 @@ void CommonRuntimeTestImpl::FinalizeSetup() {
{
ScopedObjectAccess soa(Thread::Current());
- class_linker_->RunRootClinits();
+ runtime_->RunRootClinits(soa.Self());
}
// We're back in native, take the opportunity to initialize well known classes.
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 12baede59b..edaa043ce6 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -2612,16 +2612,8 @@ mirror::Object* ConcurrentCopying::MarkNonMoving(Thread* const self,
bool is_los = mark_bitmap == nullptr;
if (!is_los && mark_bitmap->Test(ref)) {
// Already marked.
- if (kUseBakerReadBarrier) {
- DCHECK(ref->GetReadBarrierState() == ReadBarrier::GrayState() ||
- ref->GetReadBarrierState() == ReadBarrier::WhiteState());
- }
} else if (is_los && los_bitmap->Test(ref)) {
// Already marked in LOS.
- if (kUseBakerReadBarrier) {
- DCHECK(ref->GetReadBarrierState() == ReadBarrier::GrayState() ||
- ref->GetReadBarrierState() == ReadBarrier::WhiteState());
- }
} else {
// Not marked.
if (IsOnAllocStack(ref)) {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index a961cb2597..e54674f72b 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -60,6 +60,7 @@ static jobjectArray Constructor_getExceptionTypes(JNIEnv* env, jobject javaMetho
static jobject Constructor_newInstance0(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
ScopedFastNativeObjectAccess soa(env);
ObjPtr<mirror::Constructor> m = soa.Decode<mirror::Constructor>(javaMethod);
+ ArtMethod* constructor_art_method = m->GetArtMethod();
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> c(hs.NewHandle(m->GetDeclaringClass()));
if (UNLIKELY(c->IsAbstract())) {
@@ -100,18 +101,20 @@ static jobject Constructor_newInstance0(JNIEnv* env, jobject javaMethod, jobject
}
// String constructor is replaced by a StringFactory method in InvokeMethod.
- if (c->IsStringClass()) {
+ if (UNLIKELY(c->IsStringClass())) {
return InvokeMethod(soa, javaMethod, nullptr, javaArgs, 2);
}
ObjPtr<mirror::Object> receiver =
movable ? c->AllocObject(soa.Self()) : c->AllocNonMovableObject(soa.Self());
- if (receiver == nullptr) {
+ if (UNLIKELY(receiver == nullptr)) {
+ DCHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
jobject javaReceiver = soa.AddLocalReference<jobject>(receiver);
- InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, 2);
- // Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
+
+ InvokeConstructor(soa, constructor_art_method, receiver, javaArgs);
+
return javaReceiver;
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 9e9c33caa8..646de757e0 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -457,6 +457,64 @@ void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,
method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty);
}
+ALWAYS_INLINE
+bool CheckArgsForInvokeMethod(ArtMethod* np_method,
+ ObjPtr<mirror::ObjectArray<mirror::Object>> objects)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile::TypeList* classes = np_method->GetParameterTypeList();
+ uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
+ uint32_t arg_count = (objects == nullptr) ? 0 : objects->GetLength();
+ if (UNLIKELY(arg_count != classes_size)) {
+ ThrowIllegalArgumentException(StringPrintf("Wrong number of arguments; expected %d, got %d",
+ classes_size, arg_count).c_str());
+ return false;
+ }
+ return true;
+}
+
+ALWAYS_INLINE
+bool InvokeMethodImpl(const ScopedObjectAccessAlreadyRunnable& soa,
+ ArtMethod* m,
+ ArtMethod* np_method,
+ ObjPtr<mirror::Object> receiver,
+ ObjPtr<mirror::ObjectArray<mirror::Object>> objects,
+ const char** shorty,
+ JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Invoke the method.
+ uint32_t shorty_len = 0;
+ *shorty = np_method->GetShorty(&shorty_len);
+ ArgArray arg_array(*shorty, shorty_len);
+ if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method, soa.Self())) {
+ CHECK(soa.Self()->IsExceptionPending());
+ return false;
+ }
+
+ InvokeWithArgArray(soa, m, &arg_array, result, *shorty);
+
+ // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
+ if (soa.Self()->IsExceptionPending()) {
+ // If we get another exception when we are trying to wrap, then just use that instead.
+ ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
+ soa.Self()->ClearException();
+ jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException");
+ if (exception_class == nullptr) {
+ soa.Self()->AssertPendingException();
+ return false;
+ }
+ jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V");
+ CHECK(mid != nullptr);
+ jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th.get());
+ if (exception_instance == nullptr) {
+ soa.Self()->AssertPendingException();
+ return false;
+ }
+ soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
+ return false;
+ }
+
+ return true;
+}
+
} // anonymous namespace
JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
@@ -632,12 +690,7 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
ObjPtr<mirror::ObjectArray<mirror::Object>> objects =
soa.Decode<mirror::ObjectArray<mirror::Object>>(javaArgs);
auto* np_method = m->GetInterfaceMethodIfProxy(kRuntimePointerSize);
- const DexFile::TypeList* classes = np_method->GetParameterTypeList();
- uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
- uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
- if (arg_count != classes_size) {
- ThrowIllegalArgumentException(StringPrintf("Wrong number of arguments; expected %d, got %d",
- classes_size, arg_count).c_str());
+ if (!CheckArgsForInvokeMethod(np_method, objects)) {
return nullptr;
}
@@ -661,39 +714,54 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
// Invoke the method.
JValue result;
- uint32_t shorty_len = 0;
- const char* shorty = np_method->GetShorty(&shorty_len);
- ArgArray arg_array(shorty, shorty_len);
- if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method, soa.Self())) {
- CHECK(soa.Self()->IsExceptionPending());
+ const char* shorty;
+ if (!InvokeMethodImpl(soa, m, np_method, receiver, objects, &shorty, &result)) {
return nullptr;
}
+ return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
+}
- InvokeWithArgArray(soa, m, &arg_array, &result, shorty);
+void InvokeConstructor(const ScopedObjectAccessAlreadyRunnable& soa,
+ ArtMethod* constructor,
+ ObjPtr<mirror::Object> receiver,
+ jobject javaArgs) {
+ // We want to make sure that the stack is not within a small distance from the
+ // protected region in case we are calling into a leaf function whose stack
+ // check has been elided.
+ if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEndForInterpreter(true))) {
+ ThrowStackOverflowError(soa.Self());
+ return;
+ }
- // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
- if (soa.Self()->IsExceptionPending()) {
- // If we get another exception when we are trying to wrap, then just use that instead.
- ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
- soa.Self()->ClearException();
- jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException");
- if (exception_class == nullptr) {
- soa.Self()->AssertPendingException();
- return nullptr;
- }
- jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V");
- CHECK(mid != nullptr);
- jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th.get());
- if (exception_instance == nullptr) {
- soa.Self()->AssertPendingException();
- return nullptr;
- }
- soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
- return nullptr;
+ if (kIsDebugBuild) {
+ CHECK(constructor->IsConstructor());
+
+ ObjPtr<mirror::Class> declaring_class = constructor->GetDeclaringClass();
+ CHECK(declaring_class->IsInitialized());
+
+ // Calls to String.<init> should have been repplaced with with equivalent StringFactory calls.
+ CHECK(!declaring_class->IsStringClass());
+
+ // Check that the receiver is non-null and an instance of the field's declaring class.
+ CHECK(receiver != nullptr);
+ CHECK(VerifyObjectIsClass(receiver, declaring_class));
+ CHECK_EQ(constructor,
+ receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(constructor,
+ kRuntimePointerSize));
}
- // Box if necessary and return.
- return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
+ // Get our arrays of arguments and their types, and check they're the same size.
+ ObjPtr<mirror::ObjectArray<mirror::Object>> objects =
+ soa.Decode<mirror::ObjectArray<mirror::Object>>(javaArgs);
+ ArtMethod* np_method = constructor->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+ if (!CheckArgsForInvokeMethod(np_method, objects)) {
+ return;
+ }
+
+ // Invoke the constructor.
+ JValue result;
+ const char* shorty;
+ InvokeMethodImpl(soa, constructor, np_method, receiver, objects, &shorty, &result);
}
ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value) {
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 4391bcd60b..74580a21e0 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -92,6 +92,14 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa,
size_t num_frames = 1)
REQUIRES_SHARED(Locks::mutator_lock_);
+// Special-casing of the above. Assumes that the method is the correct constructor, the class is
+// initialized, and that the receiver is an instance of the class.
+void InvokeConstructor(const ScopedObjectAccessAlreadyRunnable& soa,
+ ArtMethod* constructor,
+ ObjPtr<mirror::Object> receiver,
+ jobject args)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
ALWAYS_INLINE bool VerifyObjectIsClass(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index f7674c89d3..a81c4d0518 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -713,6 +713,23 @@ std::string Runtime::GetCompilerExecutable() const {
return compiler_executable;
}
+void Runtime::RunRootClinits(Thread* self) {
+ class_linker_->RunRootClinits(self);
+
+ GcRoot<mirror::Throwable>* exceptions[] = {
+ &pre_allocated_OutOfMemoryError_when_throwing_exception_,
+ // &pre_allocated_OutOfMemoryError_when_throwing_oome_, // Same class as above.
+ // &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_, // Same class as above.
+ &pre_allocated_NoClassDefFoundError_,
+ };
+ for (GcRoot<mirror::Throwable>* exception : exceptions) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass = hs.NewHandle<mirror::Class>(exception->Read()->GetClass());
+ class_linker_->EnsureInitialized(self, klass, true, true);
+ self->AssertNoPendingException();
+ }
+}
+
bool Runtime::Start() {
VLOG(startup) << "Runtime::Start entering";
@@ -742,8 +759,10 @@ bool Runtime::Start() {
auto field_class(hs.NewHandle<mirror::Class>(GetClassRoot<mirror::Field>(class_roots)));
class_linker_->EnsureInitialized(soa.Self(), class_class, true, true);
+ self->AssertNoPendingException();
// Field class is needed for register_java_net_InetAddress in libcore, b/28153851.
class_linker_->EnsureInitialized(soa.Self(), field_class, true, true);
+ self->AssertNoPendingException();
}
// InitNativeMethods needs to be after started_ so that the classes
@@ -1090,15 +1109,30 @@ void Runtime::SetSentinel(mirror::Object* sentinel) {
sentinel_ = GcRoot<mirror::Object>(sentinel);
}
-static inline void InitPreAllocatedException(Thread* self,
- GcRoot<mirror::Throwable>* exception,
- const char* exception_class_descriptor,
- const char* msg)
+static inline void CreatePreAllocatedException(Thread* self,
+ Runtime* runtime,
+ GcRoot<mirror::Throwable>* exception,
+ const char* exception_class_descriptor,
+ const char* msg)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK_EQ(self, Thread::Current());
- self->ThrowNewException(exception_class_descriptor, msg);
- *exception = GcRoot<mirror::Throwable>(self->GetException());
- self->ClearException();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ // Allocate an object without initializing the class to allow non-trivial Throwable.<clinit>().
+ ObjPtr<mirror::Class> klass = class_linker->FindSystemClass(self, exception_class_descriptor);
+ CHECK(klass != nullptr);
+ gc::AllocatorType allocator_type = runtime->GetHeap()->GetCurrentAllocator();
+ ObjPtr<mirror::Throwable> exception_object = ObjPtr<mirror::Throwable>::DownCast(
+ klass->Alloc</* kIsInstrumented */ true>(self, allocator_type));
+ CHECK(exception_object != nullptr);
+ *exception = GcRoot<mirror::Throwable>(exception_object);
+ // Initialize the "detailMessage" field.
+ ObjPtr<mirror::String> message = mirror::String::AllocFromModifiedUtf8(self, msg);
+ CHECK(message != nullptr);
+ ObjPtr<mirror::Class> throwable = GetClassRoot<mirror::Throwable>(class_linker);
+ ArtField* detailMessageField =
+ throwable->FindDeclaredInstanceField("detailMessage", "Ljava/lang/String;");
+ CHECK(detailMessageField != nullptr);
+ detailMessageField->SetObject</* kTransactionActive */ false>(exception->Read(), message);
}
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
@@ -1543,32 +1577,36 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
} else {
// Pre-allocate an OutOfMemoryError for the case when we fail to
// allocate the exception to be thrown.
- InitPreAllocatedException(self,
- &pre_allocated_OutOfMemoryError_when_throwing_exception_,
- "Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to throw an exception; "
- "no stack trace available");
+ CreatePreAllocatedException(self,
+ this,
+ &pre_allocated_OutOfMemoryError_when_throwing_exception_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to throw an exception; "
+ "no stack trace available");
// Pre-allocate an OutOfMemoryError for the double-OOME case.
- InitPreAllocatedException(self,
- &pre_allocated_OutOfMemoryError_when_throwing_oome_,
- "Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
- "no stack trace available");
+ CreatePreAllocatedException(self,
+ this,
+ &pre_allocated_OutOfMemoryError_when_throwing_oome_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
+ "no stack trace available");
// Pre-allocate an OutOfMemoryError for the case when we fail to
// allocate while handling a stack overflow.
- InitPreAllocatedException(self,
- &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,
- "Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to handle a stack overflow; "
- "no stack trace available");
+ CreatePreAllocatedException(self,
+ this,
+ &pre_allocated_OutOfMemoryError_when_handling_stack_overflow_,
+ "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to handle a stack overflow; "
+ "no stack trace available");
// Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class
// ahead of checking the application's class loader.
- InitPreAllocatedException(self,
- &pre_allocated_NoClassDefFoundError_,
- "Ljava/lang/NoClassDefFoundError;",
- "Class not found using the boot class loader; "
- "no stack trace available");
+ CreatePreAllocatedException(self,
+ this,
+ &pre_allocated_NoClassDefFoundError_,
+ "Ljava/lang/NoClassDefFoundError;",
+ "Class not found using the boot class loader; "
+ "no stack trace available");
}
// Runtime initialization is largely done now.
diff --git a/runtime/runtime.h b/runtime/runtime.h
index d85490c0a6..f413733804 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -212,6 +212,8 @@ class Runtime {
return finished_starting_;
}
+ void RunRootClinits(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
+
static Runtime* Current() {
return instance_;
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 1a078d5fe6..19d9485f5e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2045,15 +2045,15 @@ void Thread::FinishStartup() {
// Finish attaching the main thread.
ScopedObjectAccess soa(Thread::Current());
- Thread::Current()->CreatePeer("main", false, runtime->GetMainThreadGroup());
- Thread::Current()->AssertNoPendingException();
+ soa.Self()->CreatePeer("main", false, runtime->GetMainThreadGroup());
+ soa.Self()->AssertNoPendingException();
- Runtime::Current()->GetClassLinker()->RunRootClinits();
+ runtime->RunRootClinits(soa.Self());
// The thread counts as started from now on. We need to add it to the ThreadGroup. For regular
// threads, this is done in Thread.start() on the Java side.
- Thread::Current()->NotifyThreadGroup(soa, runtime->GetMainThreadGroup());
- Thread::Current()->AssertNoPendingException();
+ soa.Self()->NotifyThreadGroup(soa, runtime->GetMainThreadGroup());
+ soa.Self()->AssertNoPendingException();
}
void Thread::Shutdown() {
diff --git a/test/etc/default-build b/test/etc/default-build
index 073ae2c796..8542ad0e92 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -321,7 +321,7 @@ function make_dexmerge() {
}
function make_hiddenapi() {
- local args=()
+ local args=( "encode" )
while [[ $# -gt 0 ]]; do
args+=("--dex=$1")
shift
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index 97e7f4cf3c..2e1ec5a541 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -61,18 +61,16 @@ NO_RETURN static void Usage(const char* fmt, ...) {
va_end(ap);
UsageError("Command: %s", CommandLine().c_str());
- UsageError("Usage: hiddenapi [options]...");
+ UsageError("Usage: hiddenapi [command_name] [options]...");
UsageError("");
- UsageError(" --dex=<filename>: specify dex file whose members' access flags are to be set.");
- UsageError(" At least one --dex parameter must be specified.");
+ UsageError(" Command \"encode\": encode API list membership in boot dex files");
+ UsageError(" --dex=<filename>: dex file which belongs to boot class path,");
+ UsageError(" the file will be overwritten");
UsageError("");
- UsageError(" --light-greylist=<filename>:");
- UsageError(" --dark-greylist=<filename>:");
- UsageError(" --blacklist=<filename>: text files with signatures of methods/fields to be marked");
- UsageError(" greylisted/blacklisted respectively. At least one list must be provided.");
- UsageError("");
- UsageError(" --print-hidden-api: dump a list of marked methods/fields to the standard output.");
- UsageError(" There is no indication which API category they belong to.");
+ UsageError(" --light-greylist=<filename>:");
+ UsageError(" --dark-greylist=<filename>:");
+ UsageError(" --blacklist=<filename>:");
+ UsageError(" text files with signatures of methods/fields to be annotated");
UsageError("");
exit(EXIT_FAILURE);
@@ -128,11 +126,6 @@ class DexMember {
UpdateUnsignedLeb128(const_cast<uint8_t*>(ptr), new_flags);
}
- // Returns true if this member's API entry is in `list`.
- bool IsOnApiList(const std::unordered_set<std::string>& list) const {
- return list.find(GetApiEntry()) != list.end();
- }
-
// Constructs a string with a unique signature of this class member.
std::string GetApiEntry() const {
std::stringstream ss;
@@ -164,112 +157,44 @@ class DexMember {
const ClassDataItemIterator& it_;
};
-class HiddenApi FINAL {
+class ClassPath FINAL {
public:
- HiddenApi() : print_hidden_api_(false) {}
-
- void ParseArgs(int argc, char** argv) {
- original_argc = argc;
- original_argv = argv;
-
- android::base::InitLogging(argv);
-
- // Skip over the command name.
- argv++;
- argc--;
-
- if (argc == 0) {
- Usage("No arguments specified");
- }
+ explicit ClassPath(const std::vector<std::string>& dex_paths) {
+ OpenDexFiles(dex_paths);
+ }
- for (int i = 0; i < argc; ++i) {
- const StringPiece option(argv[i]);
- const bool log_options = false;
- if (log_options) {
- LOG(INFO) << "hiddenapi: option[" << i << "]=" << argv[i];
- }
- if (option == "--print-hidden-api") {
- print_hidden_api_ = true;
- } else if (option.starts_with("--dex=")) {
- dex_paths_.push_back(option.substr(strlen("--dex=")).ToString());
- } else if (option.starts_with("--light-greylist=")) {
- light_greylist_path_ = option.substr(strlen("--light-greylist=")).ToString();
- } else if (option.starts_with("--dark-greylist=")) {
- dark_greylist_path_ = option.substr(strlen("--dark-greylist=")).ToString();
- } else if (option.starts_with("--blacklist=")) {
- blacklist_path_ = option.substr(strlen("--blacklist=")).ToString();
- } else {
- Usage("Unknown argument '%s'", option.data());
+ template<typename Fn>
+ void ForEachDexMember(Fn fn) {
+ for (auto& dex_file : dex_files_) {
+ for (uint32_t class_idx = 0; class_idx < dex_file->NumClassDefs(); ++class_idx) {
+ DexClass klass(*dex_file, class_idx);
+ const uint8_t* klass_data = klass.GetData();
+ if (klass_data != nullptr) {
+ for (ClassDataItemIterator it(*dex_file, klass_data); it.HasNext(); it.Next()) {
+ DexMember member(klass, it);
+ fn(member);
+ }
+ }
}
}
}
- bool ProcessDexFiles() {
- if (dex_paths_.empty()) {
- Usage("No DEX files specified");
- }
-
- if (light_greylist_path_.empty() && dark_greylist_path_.empty() && blacklist_path_.empty()) {
- Usage("No API file specified");
- }
-
- if (!light_greylist_path_.empty() && !OpenApiFile(light_greylist_path_, &light_greylist_)) {
- return false;
- }
-
- if (!dark_greylist_path_.empty() && !OpenApiFile(dark_greylist_path_, &dark_greylist_)) {
- return false;
- }
-
- if (!blacklist_path_.empty() && !OpenApiFile(blacklist_path_, &blacklist_)) {
- return false;
- }
-
- MemMap::Init();
- if (!OpenDexFiles()) {
- return false;
- }
-
- DCHECK(!dex_files_.empty());
+ void UpdateDexChecksums() {
for (auto& dex_file : dex_files_) {
- CategorizeAllClasses(*dex_file.get());
+ // Obtain a writeable pointer to the dex header.
+ DexFile::Header* header = const_cast<DexFile::Header*>(&dex_file->GetHeader());
+ // Recalculate checksum and overwrite the value in the header.
+ header->checksum_ = dex_file->CalculateChecksum();
}
-
- UpdateDexChecksums();
- return true;
}
private:
- bool OpenApiFile(const std::string& path, std::unordered_set<std::string>* list) {
- DCHECK(list->empty());
- DCHECK(!path.empty());
-
- std::ifstream api_file(path, std::ifstream::in);
- if (api_file.fail()) {
- LOG(ERROR) << "Unable to open file '" << path << "' " << strerror(errno);
- return false;
- }
-
- for (std::string line; std::getline(api_file, line);) {
- list->insert(line);
- }
-
- api_file.close();
- return true;
- }
-
- bool OpenDexFiles() {
+ void OpenDexFiles(const std::vector<std::string>& dex_paths) {
ArtDexFileLoader dex_loader;
- DCHECK(dex_files_.empty());
-
- for (const std::string& filename : dex_paths_) {
- std::string error_msg;
-
+ std::string error_msg;
+ for (const std::string& filename : dex_paths) {
File fd(filename.c_str(), O_RDWR, /* check_usage */ false);
- if (fd.Fd() == -1) {
- LOG(ERROR) << "Unable to open file '" << filename << "': " << strerror(errno);
- return false;
- }
+ CHECK_NE(fd.Fd(), -1) << "Unable to open file '" << filename << "': " << strerror(errno);
// Memory-map the dex file with MAP_SHARED flag so that changes in memory
// propagate to the underlying file. We run dex file verification as if
@@ -283,96 +208,127 @@ class HiddenApi FINAL {
/* verify_checksum */ true,
/* mmap_shared */ true,
&error_msg));
- if (dex_file.get() == nullptr) {
- LOG(ERROR) << "Open failed for '" << filename << "' " << error_msg;
- return false;
- }
+ CHECK(dex_file.get() != nullptr) << "Open failed for '" << filename << "' " << error_msg;
+ CHECK(dex_file->IsStandardDexFile()) << "Expected a standard dex file '" << filename << "'";
+ CHECK(dex_file->EnableWrite())
+ << "Failed to enable write permission for '" << filename << "'";
+ dex_files_.push_back(std::move(dex_file));
+ }
+ }
- if (!dex_file->IsStandardDexFile()) {
- LOG(ERROR) << "Expected a standard dex file '" << filename << "'";
- return false;
- }
+ // Opened DEX files. Note that these are opened as `const` but may be written into.
+ std::vector<std::unique_ptr<const DexFile>> dex_files_;
+};
- // Change the protection of the memory mapping to read-write.
- if (!dex_file->EnableWrite()) {
- LOG(ERROR) << "Failed to enable write permission for '" << filename << "'";
- return false;
- }
+class HiddenApi FINAL {
+ public:
+ HiddenApi() {}
- dex_files_.push_back(std::move(dex_file));
+ void Run(int argc, char** argv) {
+ switch (ParseArgs(argc, argv)) {
+ case Command::kEncode:
+ EncodeAccessFlags();
+ break;
}
- return true;
}
- void CategorizeAllClasses(const DexFile& dex_file) {
- for (uint32_t class_idx = 0; class_idx < dex_file.NumClassDefs(); ++class_idx) {
- DexClass klass(dex_file, class_idx);
- const uint8_t* klass_data = klass.GetData();
- if (klass_data == nullptr) {
- continue;
- }
-
- for (ClassDataItemIterator it(klass.GetDexFile(), klass_data); it.HasNext(); it.Next()) {
- DexMember member(klass, it);
-
- // Catagorize member and overwrite its access flags.
- // Note that if a member appears on multiple API lists, it will be categorized
- // as the strictest.
- bool is_hidden = true;
- if (member.IsOnApiList(blacklist_)) {
- member.SetHidden(HiddenApiAccessFlags::kBlacklist);
- } else if (member.IsOnApiList(dark_greylist_)) {
- member.SetHidden(HiddenApiAccessFlags::kDarkGreylist);
- } else if (member.IsOnApiList(light_greylist_)) {
- member.SetHidden(HiddenApiAccessFlags::kLightGreylist);
- } else {
- member.SetHidden(HiddenApiAccessFlags::kWhitelist);
- is_hidden = false;
- }
+ private:
+ enum class Command {
+ // Currently just one command. A "list" command will be added for generating
+ // a full list of boot class members.
+ kEncode,
+ };
+
+ Command ParseArgs(int argc, char** argv) {
+ // Skip over the binary's path.
+ argv++;
+ argc--;
- if (print_hidden_api_ && is_hidden) {
- std::cout << member.GetApiEntry() << std::endl;
+ if (argc > 0) {
+ const StringPiece command(argv[0]);
+ if (command == "encode") {
+ for (int i = 1; i < argc; ++i) {
+ const StringPiece option(argv[i]);
+ if (option.starts_with("--dex=")) {
+ boot_dex_paths_.push_back(option.substr(strlen("--dex=")).ToString());
+ } else if (option.starts_with("--light-greylist=")) {
+ light_greylist_path_ = option.substr(strlen("--light-greylist=")).ToString();
+ } else if (option.starts_with("--dark-greylist=")) {
+ dark_greylist_path_ = option.substr(strlen("--dark-greylist=")).ToString();
+ } else if (option.starts_with("--blacklist=")) {
+ blacklist_path_ = option.substr(strlen("--blacklist=")).ToString();
+ } else {
+ Usage("Unknown argument '%s'", option.data());
+ }
}
+ return Command::kEncode;
+ } else {
+ Usage("Unknown command '%s'", command.data());
}
+ } else {
+ Usage("No command specified");
}
}
- void UpdateDexChecksums() {
- for (auto& dex_file : dex_files_) {
- // Obtain a writeable pointer to the dex header.
- DexFile::Header* header = const_cast<DexFile::Header*>(&dex_file->GetHeader());
- // Recalculate checksum and overwrite the value in the header.
- header->checksum_ = dex_file->CalculateChecksum();
+ void EncodeAccessFlags() {
+ if (boot_dex_paths_.empty()) {
+ Usage("No boot DEX files specified");
}
+
+ // Load dex signatures.
+ std::map<std::string, HiddenApiAccessFlags::ApiList> api_list;
+ OpenApiFile(light_greylist_path_, api_list, HiddenApiAccessFlags::kLightGreylist);
+ OpenApiFile(dark_greylist_path_, api_list, HiddenApiAccessFlags::kDarkGreylist);
+ OpenApiFile(blacklist_path_, api_list, HiddenApiAccessFlags::kBlacklist);
+
+ // Open all dex files.
+ ClassPath boot_class_path(boot_dex_paths_);
+
+ // Set access flags of all members.
+ boot_class_path.ForEachDexMember([&api_list](DexMember& boot_member) {
+ auto it = api_list.find(boot_member.GetApiEntry());
+ if (it == api_list.end()) {
+ boot_member.SetHidden(HiddenApiAccessFlags::kWhitelist);
+ } else {
+ boot_member.SetHidden(it->second);
+ }
+ });
+
+ boot_class_path.UpdateDexChecksums();
}
- // Print signatures of APIs which have been grey-/blacklisted.
- bool print_hidden_api_;
+ void OpenApiFile(const std::string& path,
+ std::map<std::string, HiddenApiAccessFlags::ApiList>& api_list,
+ HiddenApiAccessFlags::ApiList membership) {
+ if (path.empty()) {
+ return;
+ }
+
+ std::ifstream api_file(path, std::ifstream::in);
+ CHECK(!api_file.fail()) << "Unable to open file '" << path << "' " << strerror(errno);
+
+ for (std::string line; std::getline(api_file, line);) {
+ CHECK(api_list.find(line) == api_list.end())
+ << "Duplicate entry: " << line << " (" << api_list[line] << " and " << membership << ")";
+ api_list.emplace(line, membership);
+ }
+ api_file.close();
+ }
// Paths to DEX files which should be processed.
- std::vector<std::string> dex_paths_;
+ std::vector<std::string> boot_dex_paths_;
// Paths to text files which contain the lists of API members.
std::string light_greylist_path_;
std::string dark_greylist_path_;
std::string blacklist_path_;
-
- // Opened DEX files. Note that these are opened as `const` but eventually will be written into.
- std::vector<std::unique_ptr<const DexFile>> dex_files_;
-
- // Signatures of DEX members loaded from `light_greylist_path_`, `dark_greylist_path_`,
- // `blacklist_path_`.
- std::unordered_set<std::string> light_greylist_;
- std::unordered_set<std::string> dark_greylist_;
- std::unordered_set<std::string> blacklist_;
};
} // namespace art
int main(int argc, char** argv) {
- art::HiddenApi hiddenapi;
-
- // Parse arguments. Argument mistakes will lead to exit(EXIT_FAILURE) in UsageError.
- hiddenapi.ParseArgs(argc, argv);
- return hiddenapi.ProcessDexFiles() ? EXIT_SUCCESS : EXIT_FAILURE;
+ android::base::InitLogging(argv);
+ art::MemMap::Init();
+ art::HiddenApi().Run(argc, argv);
+ return EXIT_SUCCESS;
}
diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc
index ed880e0e92..aa87f21e7f 100644
--- a/tools/hiddenapi/hiddenapi_test.cc
+++ b/tools/hiddenapi/hiddenapi_test.cc
@@ -66,15 +66,18 @@ class HiddenApiTest : public CommonRuntimeTest {
std::vector<std::string> argv_str;
argv_str.push_back(GetHiddenApiCmd());
argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
+ argv_str.push_back("encode");
argv_str.push_back("--dex=" + out_dex->GetFilename());
argv_str.push_back("--light-greylist=" + light_greylist.GetFilename());
argv_str.push_back("--dark-greylist=" + dark_greylist.GetFilename());
argv_str.push_back("--blacklist=" + blacklist.GetFilename());
int return_code = ExecAndReturnCode(argv_str, &error);
- if (return_code != 0) {
- LOG(FATAL) << "HiddenApi binary exited with unexpected return code " << return_code;
+ if (return_code == 0) {
+ return OpenDex(*out_dex);
+ } else {
+ LOG(ERROR) << "HiddenApi binary exited with unexpected return code " << return_code;
+ return nullptr;
}
- return OpenDex(*out_dex);
}
std::unique_ptr<const DexFile> OpenDex(const ScratchFile& file) {
@@ -226,6 +229,7 @@ TEST_F(HiddenApiTest, InstanceFieldNoMatch) {
OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kWhitelist, GetIFieldHiddenFlags(*dex_file));
}
@@ -235,6 +239,7 @@ TEST_F(HiddenApiTest, InstanceFieldLightGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kLightGreylist, GetIFieldHiddenFlags(*dex_file));
}
@@ -244,6 +249,7 @@ TEST_F(HiddenApiTest, InstanceFieldDarkGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->ifield:I" << std::endl;
OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetIFieldHiddenFlags(*dex_file));
}
@@ -253,6 +259,7 @@ TEST_F(HiddenApiTest, InstanceFieldBlacklistMatch) {
OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->ifield:I" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetIFieldHiddenFlags(*dex_file));
}
@@ -262,7 +269,7 @@ TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch1) {
OpenStream(dark_greylist) << "LMain;->ifield:I" << std::endl;
OpenStream(blacklist) << "LMain;->ifield:I" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetIFieldHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch2) {
@@ -271,7 +278,7 @@ TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch2) {
OpenStream(dark_greylist) << "LMain;->ifield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->ifield:I" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetIFieldHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch3) {
@@ -280,7 +287,7 @@ TEST_F(HiddenApiTest, InstanceFieldTwoListsMatch3) {
OpenStream(dark_greylist) << "LMain;->ifield:I" << std::endl;
OpenStream(blacklist) << "LMain;->ifield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetIFieldHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticFieldNoMatch) {
@@ -289,6 +296,7 @@ TEST_F(HiddenApiTest, StaticFieldNoMatch) {
OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kWhitelist, GetSFieldHiddenFlags(*dex_file));
}
@@ -298,6 +306,7 @@ TEST_F(HiddenApiTest, StaticFieldLightGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kLightGreylist, GetSFieldHiddenFlags(*dex_file));
}
@@ -307,6 +316,7 @@ TEST_F(HiddenApiTest, StaticFieldDarkGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetSFieldHiddenFlags(*dex_file));
}
@@ -316,6 +326,7 @@ TEST_F(HiddenApiTest, StaticFieldBlacklistMatch) {
OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSFieldHiddenFlags(*dex_file));
}
@@ -325,7 +336,7 @@ TEST_F(HiddenApiTest, StaticFieldTwoListsMatch1) {
OpenStream(dark_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
OpenStream(blacklist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSFieldHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticFieldTwoListsMatch2) {
@@ -334,7 +345,7 @@ TEST_F(HiddenApiTest, StaticFieldTwoListsMatch2) {
OpenStream(dark_greylist) << "LMain;->sfield:LBadType2;" << std::endl;
OpenStream(blacklist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSFieldHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticFieldTwoListsMatch3) {
@@ -343,7 +354,7 @@ TEST_F(HiddenApiTest, StaticFieldTwoListsMatch3) {
OpenStream(dark_greylist) << "LMain;->sfield:Ljava/lang/Object;" << std::endl;
OpenStream(blacklist) << "LMain;->sfield:LBadType3;" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetSFieldHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceMethodNoMatch) {
@@ -352,6 +363,7 @@ TEST_F(HiddenApiTest, InstanceMethodNoMatch) {
OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kWhitelist, GetIMethodHiddenFlags(*dex_file));
}
@@ -361,6 +373,7 @@ TEST_F(HiddenApiTest, InstanceMethodLightGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kLightGreylist, GetIMethodHiddenFlags(*dex_file));
}
@@ -370,6 +383,7 @@ TEST_F(HiddenApiTest, InstanceMethodDarkGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->imethod(J)V" << std::endl;
OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetIMethodHiddenFlags(*dex_file));
}
@@ -379,6 +393,7 @@ TEST_F(HiddenApiTest, InstanceMethodBlacklistMatch) {
OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->imethod(J)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetIMethodHiddenFlags(*dex_file));
}
@@ -388,7 +403,7 @@ TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch1) {
OpenStream(dark_greylist) << "LMain;->imethod(J)V" << std::endl;
OpenStream(blacklist) << "LMain;->imethod(J)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetIMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch2) {
@@ -397,7 +412,7 @@ TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch2) {
OpenStream(dark_greylist) << "LMain;->imethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->imethod(J)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetIMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch3) {
@@ -406,7 +421,7 @@ TEST_F(HiddenApiTest, InstanceMethodTwoListsMatch3) {
OpenStream(dark_greylist) << "LMain;->imethod(J)V" << std::endl;
OpenStream(blacklist) << "LMain;->imethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetIMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticMethodNoMatch) {
@@ -415,6 +430,7 @@ TEST_F(HiddenApiTest, StaticMethodNoMatch) {
OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kWhitelist, GetSMethodHiddenFlags(*dex_file));
}
@@ -424,6 +440,7 @@ TEST_F(HiddenApiTest, StaticMethodLightGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kLightGreylist, GetSMethodHiddenFlags(*dex_file));
}
@@ -433,6 +450,7 @@ TEST_F(HiddenApiTest, StaticMethodDarkGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetSMethodHiddenFlags(*dex_file));
}
@@ -442,6 +460,7 @@ TEST_F(HiddenApiTest, StaticMethodBlacklistMatch) {
OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSMethodHiddenFlags(*dex_file));
}
@@ -451,7 +470,7 @@ TEST_F(HiddenApiTest, StaticMethodTwoListsMatch1) {
OpenStream(dark_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
OpenStream(blacklist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticMethodTwoListsMatch2) {
@@ -460,7 +479,7 @@ TEST_F(HiddenApiTest, StaticMethodTwoListsMatch2) {
OpenStream(dark_greylist) << "LMain;->smethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticMethodTwoListsMatch3) {
@@ -469,7 +488,7 @@ TEST_F(HiddenApiTest, StaticMethodTwoListsMatch3) {
OpenStream(dark_greylist) << "LMain;->smethod(Ljava/lang/Object;)V" << std::endl;
OpenStream(blacklist) << "LMain;->smethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetSMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceNativeMethodNoMatch) {
@@ -478,6 +497,7 @@ TEST_F(HiddenApiTest, InstanceNativeMethodNoMatch) {
OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kWhitelist, GetINMethodHiddenFlags(*dex_file));
}
@@ -487,6 +507,7 @@ TEST_F(HiddenApiTest, InstanceNativeMethodLightGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kLightGreylist, GetINMethodHiddenFlags(*dex_file));
}
@@ -496,6 +517,7 @@ TEST_F(HiddenApiTest, InstanceNativeMethodDarkGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->inmethod(C)V" << std::endl;
OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetINMethodHiddenFlags(*dex_file));
}
@@ -505,6 +527,7 @@ TEST_F(HiddenApiTest, InstanceNativeMethodBlacklistMatch) {
OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->inmethod(C)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetINMethodHiddenFlags(*dex_file));
}
@@ -514,7 +537,7 @@ TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch1) {
OpenStream(dark_greylist) << "LMain;->inmethod(C)V" << std::endl;
OpenStream(blacklist) << "LMain;->inmethod(C)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetINMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch2) {
@@ -523,7 +546,7 @@ TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch2) {
OpenStream(dark_greylist) << "LMain;->inmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->inmethod(C)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetINMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch3) {
@@ -532,7 +555,7 @@ TEST_F(HiddenApiTest, InstanceNativeMethodTwoListsMatch3) {
OpenStream(dark_greylist) << "LMain;->inmethod(C)V" << std::endl;
OpenStream(blacklist) << "LMain;->inmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetINMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticNativeMethodNoMatch) {
@@ -541,6 +564,7 @@ TEST_F(HiddenApiTest, StaticNativeMethodNoMatch) {
OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kWhitelist, GetSNMethodHiddenFlags(*dex_file));
}
@@ -550,6 +574,7 @@ TEST_F(HiddenApiTest, StaticNativeMethodLightGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kLightGreylist, GetSNMethodHiddenFlags(*dex_file));
}
@@ -559,6 +584,7 @@ TEST_F(HiddenApiTest, StaticNativeMethodDarkGreylistMatch) {
OpenStream(dark_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetSNMethodHiddenFlags(*dex_file));
}
@@ -568,6 +594,7 @@ TEST_F(HiddenApiTest, StaticNativeMethodBlacklistMatch) {
OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
+ ASSERT_NE(dex_file.get(), nullptr);
ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSNMethodHiddenFlags(*dex_file));
}
@@ -577,7 +604,7 @@ TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch1) {
OpenStream(dark_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
OpenStream(blacklist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSNMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch2) {
@@ -586,7 +613,7 @@ TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch2) {
OpenStream(dark_greylist) << "LMain;->snmethod(LBadType2;)V" << std::endl;
OpenStream(blacklist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kBlacklist, GetSNMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch3) {
@@ -595,7 +622,7 @@ TEST_F(HiddenApiTest, StaticNativeMethodTwoListsMatch3) {
OpenStream(dark_greylist) << "LMain;->snmethod(Ljava/lang/Integer;)V" << std::endl;
OpenStream(blacklist) << "LMain;->snmethod(LBadType3;)V" << std::endl;
auto dex_file = RunHiddenApi(light_greylist, dark_greylist, blacklist, {}, &dex);
- ASSERT_EQ(HiddenApiAccessFlags::kDarkGreylist, GetSNMethodHiddenFlags(*dex_file));
+ ASSERT_EQ(dex_file.get(), nullptr);
}
} // namespace art