// Opaque implementation of ADexFile for the C interface. struct ADexFile { explicit ADexFile(std::unique_ptr<const art::DexFile> dex_file)
: dex_file_(std::move(dex_file)) {}
void CreateClassCache() { // Create binary search table with (end_dex_offset, class_def_index) entries. // That is, we don't assume that dex code of given class is consecutive.
std::deque<std::pair<uint32_t, uint32_t>> cache; for (art::ClassAccessor accessor : dex_file_->GetClasses()) { for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
art::CodeItemInstructionAccessor code = method.GetInstructions(); if (code.HasCodeItem()) {
int32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
DCHECK_NE(offset, 0);
cache.emplace_back(offset + code.InsnsSizeInBytes(), accessor.GetClassDefIndex());
}
}
}
std::sort(cache.begin(), cache.end());
// If two consecutive methods belong to same class, we can merge them. // This tends to reduce the number of entries (used memory) by 10x.
size_t num_entries = cache.size(); if (cache.size() > 1) { for (auto it = std::next(cache.begin()); it != cache.end(); it++) { if (std::prev(it)->second == it->second) {
std::prev(it)->first = 0; // Clear entry with lower end_dex_offset (mark to remove).
num_entries--;
}
}
}
// The cache is immutable now. Store it as continuous vector to save space.
class_cache_.reserve(num_entries); auto pred = [](auto it) { return it.first != 0; }; // Entries to copy (not cleared above).
std::copy_if(cache.begin(), cache.end(), std::back_inserter(class_cache_), pred);
}
// Binary search in the class cache. First element of the pair is the key. auto comp = [](uint32_t value, constauto& it) { return value < it.first; }; auto it = std::upper_bound(class_cache_.begin(), class_cache_.end(), dex_offset, comp); if (it != class_cache_.end()) {
*class_def_index = it->second; returntrue;
} returnfalse;
}
// The underlying ART object.
std::unique_ptr<const art::DexFile> dex_file_;
uint32_t dex_size = header->file_size_; // Size of "one dex file" excluding any shared data.
uint32_t full_size = dex_size; // Includes referenced shared data past the end of dex. if (art::StandardDexFile::IsMagicValid(header->magic_)) {
full_size = header->ContainerSize() - header->HeaderOffset();
} else { return ADEXFILE_ERROR_INVALID_HEADER;
}
if (size < full_size) { if (new_size != nullptr) {
*new_size = full_size;
} return ADEXFILE_ERROR_NOT_ENOUGH_DATA;
}
size_t ADexFile_findMethodAtOffset(ADexFile* self,
size_t dex_offset,
ADexFile_MethodCallback* callback, void* callback_data) { const art::DexFile* dex_file = self->dex_file_.get(); if (!dex_file->IsInDataSection(dex_file->Begin() + dex_offset)) { return0; // The DEX offset is not within the bytecode of this dex file.
}
ADexFile_Method info; if (!self->FindMethod(dex_offset, &info)) { return0;
}
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.