item->SetDouble(conv.d);
break;
}
+ case DexFile::kDexAnnotationMethodType: {
+ const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetProtoId(GetProtoId(proto_index));
+ break;
+ }
+ case DexFile::kDexAnnotationMethodHandle: {
+ const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetMethodHandle(GetMethodHandle(method_handle_index));
+ break;
+ }
case DexFile::kDexAnnotationString: {
const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
item->SetStringId(GetStringId(string_index));
return class_data;
}
+void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
+ // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
+ const DexFile::MapList* map =
+ reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset());
+ for (uint32_t i = 0; i < map->size_; ++i) {
+ const DexFile::MapItem* item = map->list_ + i;
+ switch (item->type_) {
+ case DexFile::kDexTypeCallSiteIdItem:
+ SetCallSiteIdsOffset(item->offset_);
+ break;
+ case DexFile::kDexTypeMethodHandleItem:
+ SetMethodHandleItemsOffset(item->offset_);
+ break;
+ default:
+ break;
+ }
+ }
+ // Populate MethodHandleItems first (CallSiteIds may depend on them).
+ for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
+ CreateMethodHandleItem(dex_file, i);
+ }
+ // Populate CallSiteIds.
+ for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
+ CreateCallSiteId(dex_file, i);
+ }
+}
+
+void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
+ const uint8_t* disk_call_item_ptr = dex_file.Begin() + disk_call_site_id.data_off_;
+ EncodedArrayItem* call_site_item =
+ CreateEncodedArrayItem(disk_call_item_ptr, disk_call_site_id.data_off_);
+
+ CallSiteId* call_site_id = new CallSiteId(call_site_item);
+ call_site_ids_.AddIndexedItem(call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i);
+}
+
+void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
+ const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
+ uint16_t index = disk_method_handle.field_or_method_idx_;
+ DexFile::MethodHandleType type =
+ static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
+ bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
+ type == DexFile::MethodHandleType::kInvokeInstance ||
+ type == DexFile::MethodHandleType::kInvokeConstructor;
+ static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeConstructor,
+ "Unexpected method handle types.");
+ IndexedItem* field_or_method_id;
+ if (is_invoke) {
+ field_or_method_id = GetMethodId(index);
+ } else {
+ field_or_method_id = GetFieldId(index);
+ }
+ MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id);
+ method_handle_items_.AddIndexedItem(
+ method_handle, MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), i);
+}
+
static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
return 0;
}
&dex_ir::Collections::ClassDefsSize,
&dex_ir::Collections::ClassDefsOffset
}, {
+ "CallSiteId",
+ DexFile::kDexTypeCallSiteIdItem,
+ &dex_ir::Collections::CallSiteIdsSize,
+ &dex_ir::Collections::CallSiteIdsOffset
+ }, {
+ "MethodHandle",
+ DexFile::kDexTypeMethodHandleItem,
+ &dex_ir::Collections::MethodHandleItemsSize,
+ &dex_ir::Collections::MethodHandleItemsOffset
+ }, {
"StringData",
DexFile::kDexTypeStringDataItem,
&dex_ir::Collections::StringDatasSize,
class AnnotationsDirectoryItem;
class AnnotationSetItem;
class AnnotationSetRefList;
+class CallSiteId;
class ClassData;
class ClassDef;
class CodeItem;
class Header;
class MapList;
class MapItem;
+class MethodHandleItem;
class MethodId;
class MethodItem;
class ParameterAnnotation;
static constexpr size_t kFieldIdItemSize = 8;
static constexpr size_t kMethodIdItemSize = 8;
static constexpr size_t kClassDefItemSize = 32;
+static constexpr size_t kCallSiteIdItemSize = 4;
+static constexpr size_t kMethodHandleItemSize = 8;
// Visitor support
class AbstractDispatcher {
virtual void Dispatch(const ProtoId* proto_id) = 0;
virtual void Dispatch(const FieldId* field_id) = 0;
virtual void Dispatch(const MethodId* method_id) = 0;
+ virtual void Dispatch(const CallSiteId* call_site_id) = 0;
+ virtual void Dispatch(const MethodHandleItem* method_handle_item) = 0;
virtual void Dispatch(ClassData* class_data) = 0;
virtual void Dispatch(ClassDef* class_def) = 0;
virtual void Dispatch(FieldItem* field_item) = 0;
std::vector<std::unique_ptr<FieldId>>& FieldIds() { return field_ids_.Collection(); }
std::vector<std::unique_ptr<MethodId>>& MethodIds() { return method_ids_.Collection(); }
std::vector<std::unique_ptr<ClassDef>>& ClassDefs() { return class_defs_.Collection(); }
+ std::vector<std::unique_ptr<CallSiteId>>& CallSiteIds() { return call_site_ids_.Collection(); }
+ std::vector<std::unique_ptr<MethodHandleItem>>& MethodHandleItems()
+ { return method_handle_items_.Collection(); }
std::map<uint32_t, std::unique_ptr<StringData>>& StringDatas()
{ return string_datas_.Collection(); }
std::map<uint32_t, std::unique_ptr<TypeList>>& TypeLists() { return type_lists_.Collection(); }
void CreateFieldId(const DexFile& dex_file, uint32_t i);
void CreateMethodId(const DexFile& dex_file, uint32_t i);
void CreateClassDef(const DexFile& dex_file, uint32_t i);
+ void CreateCallSiteId(const DexFile& dex_file, uint32_t i);
+ void CreateMethodHandleItem(const DexFile& dex_file, uint32_t i);
+
+ void CreateCallSitesAndMethodHandles(const DexFile& dex_file);
TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset);
EncodedArrayItem* CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset);
FieldId* GetFieldId(uint32_t index) { return FieldIds()[index].get(); }
MethodId* GetMethodId(uint32_t index) { return MethodIds()[index].get(); }
ClassDef* GetClassDef(uint32_t index) { return ClassDefs()[index].get(); }
+ CallSiteId* GetCallSiteId(uint32_t index) { return CallSiteIds()[index].get(); }
+ MethodHandleItem* GetMethodHandle(uint32_t index) { return MethodHandleItems()[index].get(); }
StringId* GetStringIdOrNullPtr(uint32_t index) {
return index == DexFile::kDexNoIndex ? nullptr : GetStringId(index);
uint32_t FieldIdsOffset() const { return field_ids_.GetOffset(); }
uint32_t MethodIdsOffset() const { return method_ids_.GetOffset(); }
uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); }
+ uint32_t CallSiteIdsOffset() const { return call_site_ids_.GetOffset(); }
+ uint32_t MethodHandleItemsOffset() const { return method_handle_items_.GetOffset(); }
uint32_t StringDatasOffset() const { return string_datas_.GetOffset(); }
uint32_t TypeListsOffset() const { return type_lists_.GetOffset(); }
uint32_t EncodedArrayItemsOffset() const { return encoded_array_items_.GetOffset(); }
void SetFieldIdsOffset(uint32_t new_offset) { field_ids_.SetOffset(new_offset); }
void SetMethodIdsOffset(uint32_t new_offset) { method_ids_.SetOffset(new_offset); }
void SetClassDefsOffset(uint32_t new_offset) { class_defs_.SetOffset(new_offset); }
+ void SetCallSiteIdsOffset(uint32_t new_offset) { call_site_ids_.SetOffset(new_offset); }
+ void SetMethodHandleItemsOffset(uint32_t new_offset)
+ { method_handle_items_.SetOffset(new_offset); }
void SetStringDatasOffset(uint32_t new_offset) { string_datas_.SetOffset(new_offset); }
void SetTypeListsOffset(uint32_t new_offset) { type_lists_.SetOffset(new_offset); }
void SetEncodedArrayItemsOffset(uint32_t new_offset)
uint32_t FieldIdsSize() const { return field_ids_.Size(); }
uint32_t MethodIdsSize() const { return method_ids_.Size(); }
uint32_t ClassDefsSize() const { return class_defs_.Size(); }
+ uint32_t CallSiteIdsSize() const { return call_site_ids_.Size(); }
+ uint32_t MethodHandleItemsSize() const { return method_handle_items_.Size(); }
uint32_t StringDatasSize() const { return string_datas_.Size(); }
uint32_t TypeListsSize() const { return type_lists_.Size(); }
uint32_t EncodedArrayItemsSize() const { return encoded_array_items_.Size(); }
CollectionVector<FieldId> field_ids_;
CollectionVector<MethodId> method_ids_;
CollectionVector<ClassDef> class_defs_;
+ CollectionVector<CallSiteId> call_site_ids_;
+ CollectionVector<MethodHandleItem> method_handle_items_;
CollectionMap<StringData> string_datas_;
CollectionMap<TypeList> type_lists_;
void SetDouble(double d) { u_.double_val_ = d; }
void SetStringId(StringId* string_id) { u_.string_val_ = string_id; }
void SetTypeId(TypeId* type_id) { u_.type_val_ = type_id; }
+ void SetProtoId(ProtoId* proto_id) { u_.proto_val_ = proto_id; }
void SetFieldId(FieldId* field_id) { u_.field_val_ = field_id; }
void SetMethodId(MethodId* method_id) { u_.method_val_ = method_id; }
+ void SetMethodHandle(MethodHandleItem* method_handle) { u_.method_handle_val_ = method_handle; }
void SetEncodedArray(EncodedArrayItem* encoded_array) { encoded_array_.reset(encoded_array); }
void SetEncodedAnnotation(EncodedAnnotation* encoded_annotation)
{ encoded_annotation_.reset(encoded_annotation); }
double GetDouble() const { return u_.double_val_; }
StringId* GetStringId() const { return u_.string_val_; }
TypeId* GetTypeId() const { return u_.type_val_; }
+ ProtoId* GetProtoId() const { return u_.proto_val_; }
FieldId* GetFieldId() const { return u_.field_val_; }
MethodId* GetMethodId() const { return u_.method_val_; }
+ MethodHandleItem* GetMethodHandle() const { return u_.method_handle_val_; }
EncodedArrayItem* GetEncodedArray() const { return encoded_array_.get(); }
EncodedAnnotation* GetEncodedAnnotation() const { return encoded_annotation_.get(); }
double double_val_;
StringId* string_val_;
TypeId* type_val_;
+ ProtoId* proto_val_;
FieldId* field_val_;
MethodId* method_val_;
+ MethodHandleItem* method_handle_val_;
} u_;
std::unique_ptr<EncodedArrayItem> encoded_array_;
std::unique_ptr<EncodedAnnotation> encoded_annotation_;
DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem);
};
+class CallSiteId : public IndexedItem {
+ public:
+ explicit CallSiteId(EncodedArrayItem* call_site_item) : call_site_item_(call_site_item) {
+ size_ = kCallSiteIdItemSize;
+ }
+ ~CallSiteId() OVERRIDE { }
+
+ static size_t ItemSize() { return kCallSiteIdItemSize; }
+
+ EncodedArrayItem* CallSiteItem() const { return call_site_item_; }
+
+ void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
+
+ private:
+ EncodedArrayItem* call_site_item_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallSiteId);
+};
+
+class MethodHandleItem : public IndexedItem {
+ public:
+ MethodHandleItem(DexFile::MethodHandleType method_handle_type, IndexedItem* field_or_method_id)
+ : method_handle_type_(method_handle_type),
+ field_or_method_id_(field_or_method_id) {
+ size_ = kMethodHandleItemSize;
+ }
+ ~MethodHandleItem() OVERRIDE { }
+
+ static size_t ItemSize() { return kMethodHandleItemSize; }
+
+ DexFile::MethodHandleType GetMethodHandleType() const { return method_handle_type_; }
+ IndexedItem* GetFieldOrMethodId() const { return field_or_method_id_; }
+
+ void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
+
+ private:
+ DexFile::MethodHandleType method_handle_type_;
+ IndexedItem* field_or_method_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(MethodHandleItem);
+};
+
// TODO(sehr): implement MapList.
class MapList : public Item {
public:
}
// MapItem.
collections.SetMapListOffset(disk_header.map_off_);
+ // CallSiteIds and MethodHandleItems.
+ collections.CreateCallSitesAndMethodHandles(dex_file);
CheckAndSetRemainingOffsets(dex_file, &collections);
CHECK_EQ(item->size_, collections->ClassDefsSize());
CHECK_EQ(item->offset_, collections->ClassDefsOffset());
break;
+ case DexFile::kDexTypeCallSiteIdItem:
+ CHECK_EQ(item->size_, collections->CallSiteIdsSize());
+ CHECK_EQ(item->offset_, collections->CallSiteIdsOffset());
+ break;
+ case DexFile::kDexTypeMethodHandleItem:
+ CHECK_EQ(item->size_, collections->MethodHandleItemsSize());
+ CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset());
+ break;
case DexFile::kDexTypeMapList:
CHECK_EQ(item->size_, 1u);
CHECK_EQ(item->offset_, disk_header.map_off_);
length = EncodeDoubleValue(encoded_value->GetDouble(), buffer);
start = 8 - length;
break;
+ case DexFile::kDexAnnotationMethodType:
+ length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer);
+ break;
+ case DexFile::kDexAnnotationMethodHandle:
+ length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer);
+ break;
case DexFile::kDexAnnotationString:
length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
break;
}
}
+void DexWriter::WriteCallSites() {
+ uint32_t call_site_off[1];
+ for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id :
+ header_->GetCollections().CallSiteIds()) {
+ call_site_off[0] = call_site_id->CallSiteItem()->GetOffset();
+ Write(call_site_off, call_site_id->GetSize(), call_site_id->GetOffset());
+ }
+}
+
+void DexWriter::WriteMethodHandles() {
+ uint16_t method_handle_buff[4];
+ for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle :
+ header_->GetCollections().MethodHandleItems()) {
+ method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType());
+ method_handle_buff[1] = 0; // unused.
+ method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex();
+ method_handle_buff[3] = 0; // unused.
+ Write(method_handle_buff, method_handle->GetSize(), method_handle->GetOffset());
+ }
+}
+
struct MapItemContainer {
MapItemContainer(uint32_t type, uint32_t size, uint32_t offset)
: type_(type), size_(size), offset_(offset) { }
queue.push(MapItemContainer(DexFile::kDexTypeClassDefItem, collection.ClassDefsSize(),
collection.ClassDefsOffset()));
}
+ if (collection.CallSiteIdsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeCallSiteIdItem, collection.CallSiteIdsSize(),
+ collection.CallSiteIdsOffset()));
+ }
+ if (collection.MethodHandleItemsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeMethodHandleItem,
+ collection.MethodHandleItemsSize(), collection.MethodHandleItemsOffset()));
+ }
// Data section.
queue.push(MapItemContainer(DexFile::kDexTypeMapList, 1, collection.MapListOffset()));
uint32_t class_defs_off = collections.ClassDefsOffset();
buffer[16] = class_defs_size;
buffer[17] = class_defs_off;
- uint32_t data_off = class_defs_off + class_defs_size * dex_ir::ClassDef::ItemSize();
- uint32_t data_size = file_size - data_off;
- buffer[18] = data_size;
- buffer[19] = data_off;
+ buffer[18] = header_->DataSize();
+ buffer[19] = header_->DataOffset();
Write(buffer, 20 * sizeof(uint32_t), offset);
}
WriteDebugInfoItems();
WriteCodeItems();
WriteClasses();
+ WriteCallSites();
+ WriteMethodHandles();
WriteMapItem();
WriteHeader();
}
void WriteDebugInfoItems();
void WriteCodeItems();
void WriteClasses();
+ void WriteCallSites();
+ void WriteMethodHandles();
void WriteMapItem();
void WriteHeader();
uint32_t method_ids_off_; // file offset of MethodIds array
uint32_t class_defs_size_; // number of ClassDefs
uint32_t class_defs_off_; // file offset of ClassDef array
- uint32_t data_size_; // unused
- uint32_t data_off_; // unused
+ uint32_t data_size_; // size of data section
+ uint32_t data_off_; // file offset of data section
// Decode the dex magic version
uint32_t GetVersion() const;