Thaoly
Thaoly
Thaoly
h"
<limits.h>
<stdio.h>
<stdlib.h>
<string.h>
<zlib.h>
<memory>
<optional>
<ostream>
<sstream>
<type_traits>
"android”Ios-base/stringprintf.h"
"base/enums.h"
"base/hiddenapi_domain.h"
"base/leb128.h"
"base/stl_util.h"
"class_accessor-inl.h"
"descriptors_names.h"
"dex_file-inl.h"
"standard_dex_file.h"
"utf-inl.h"
art {
using android::base::StringPrintf;
using dex::CallSiteIdItem;
using dex::ClassDef;
using dex::FieldId;
using dex::MapList;
using dex::MapItem;
using dex::MethodHandleItem;
using dex::MethodId;
using dex::ProtoId;
using dex::StringId;
using dex::TryItem;
using dex::TypeId;
using dex::TypeList;
InitializeSectionsFromMapList();
}
DexFile::~DexFile() {
// We don't call DeleteGlobalRef on dex_object_ because we're only called by
DestroyJavaVM, and
// that's only called after DetachCurrentThread, which means there's no JNIEnv.
We could
// re-attach, but cleaning up these global references is not obviously useful.
It's not as if
// the global reference table is otherwise empty!
}
void DexFile::InitializeSectionsFromMapList() {
static_assert(sizeof(MapList) <= sizeof(Header));
DCHECK_GE(DataSize(), sizeof(MapList));
if (header_->map_off_ == 0 || header_->map_off_ > DataSize() - sizeof(MapList)) {
// Bad offset. The dex file verifier runs after this method and will reject the
file.
return;
}
const MapList* map_list = reinterpret_cast<const MapList*>(DataBegin() + header_-
>map_off_);
const size_t count = map_list->size_;
size_t map_limit =
(DataSize() - OFFSETOF_MEMBER(MapList, list_) - header_->map_off_) /
sizeof(MapItem);
if (count > map_limit) {
// Too many items. The dex file verifier runs after
// this method and will reject the file as it is malformed.
return;
}
// Construct pointers to certain arrays without any checks. If they are outside
the
// data, the dex file verification should fail and these pointers should not be
used.
for (size_t i = 0; i < count; ++i) {
const MapItem& map_item = map_list->list_[i];
if (map_item.type_ == kDexTypeMethodHandleItem) {
method_handles_ = reinterpret_cast<const MethodHandleItem*>(Begin() +
map_item.offset_);
num_method_handles_ = map_item.size_;
} else if (map_item.type_ == kDexTypeCallSiteIdItem) {
call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(Begin() +
map_item.offset_);
num_call_site_ids_ = map_item.size_;
} else if (map_item.type_ == kDexTypeHiddenapiClassData) {
hiddenapi_class_data_ =
reinterpret_cast<const dex::HiddenapiClassData*>(DataBegin() +
map_item.offset_);
} else {
// Pointers to other sections are not necessary to retain in the DexFile
struct.
// Other items have pointers directly into their data.
}
}
}
// Given a signature place the type ids into the given vector
bool DexFile::CreateTypeList(std::string_view signature,
dex::TypeIndex* return_type_idx,
std::vector<dex::TypeIndex>* param_type_idxs) const {
if (signature[0] != '(') {
return false;
}
size_t offset = 1;
size_t end = signature.size();
bool process_return = false;
while (offset < end) {
size_t start_offset = offset;
char c = signature[offset];
offset++;
if (c == ')') {
process_return = true;
continue;
}
while (c == '[') { // process array prefix
if (offset >= end) { // expect some descriptor following [
return false;
}
c = signature[offset];
offset++;
}
if (c == 'L') { // process type descriptors
do {
if (offset >= end) { // unexpected early termination of descriptor
return false;
}
c = signature[offset];
offset++;
} while (c != ';');
}
// TODO: avoid creating a std::string just to get a 0-terminated char array
std::string descriptor(signature.data() + start_offset, offset - start_offset);
const TypeId* type_id = FindTypeId(descriptor.c_str());
if (type_id == nullptr) {
return false;
}
dex::TypeIndex type_idx = GetIndexForTypeId(*type_id);
if (!process_return) {
param_type_idxs->push_back(type_idx);
} else {
*return_type_idx = type_idx;
return offset == end; // return true if the signature had reached a sensible
end
}
}
return false; // failed to correctly parse return type
}
void EncodedArrayValueIterator::Next() {
pos_++;
if (pos_ >= array_size_) {
return;
}
uint8_t value_type = *ptr_++;
uint8_t value_arg = value_type >> kEncodedValueArgShift;
size_t width = value_arg + 1; // assume and correct later
type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
switch (type_) {
case kBoolean:
jval_.i = (value_arg != 0) ? 1 : 0;
width = 0;
break;
case kByte:
jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
CHECK(IsInt<8>(jval_.i));
break;
case kShort:
jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
CHECK(IsInt<16>(jval_.i));
break;
case kChar:
jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
CHECK(IsUint<16>(jval_.i));
break;
case kInt:
jval_.i = DexFile::ReadSignedInt(ptr_, value_arg);
break;
case kLong:
jval_.j = DexFile::ReadSignedLong(ptr_, value_arg);
break;
case kFloat:
jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, true);
break;
case kDouble:
jval_.j = DexFile::ReadUnsignedLong(ptr_, value_arg, true);
break;
case kString:
case kType:
case kMethodType:
case kMethodHandle:
jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
break;
case kField:
case kMethod:
case kEnum:
case kArray:
case kAnnotation:
UNIMPLEMENTED(FATAL) << ": type " << type_;
UNREACHABLE();
case kNull:
jval_.l = nullptr;
width = 0;
break;
default:
LOG(FATAL) << "Unreached";
UNREACHABLE();
}
ptr_ += width;
}
namespace dex {