Revert "Revert "Add dex file writer to dexlayout tool.""
This reverts commit fd1a6c2a08ca3e2476b7424b9b0fa58e73b29e87.
Fixed output being clobbered during DexLayoutTest.DexFileOutput.
Option added to put dex output file in scratch directory.
Bug: 29921113
Test: mm test-art-host-gtest-dexlayout_test
Change-Id: I9e6b139cf06aaa39c83ad1e74329db266464a8e4
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 0987df7..b9266f7 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -21,6 +21,7 @@
"dex_ir.cc",
"dex_ir_builder.cc",
"dex_visualize.cc",
+ "dex_writer.cc",
],
cflags: ["-Wall"],
shared_libs: [
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index aff03cd..bc909c3 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -55,6 +55,54 @@
entry.end_address_, entry.reg_)));
}
+static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
+ const uint8_t* stream = debug_info_stream;
+ DecodeUnsignedLeb128(&stream); // line_start
+ uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
+ for (uint32_t i = 0; i < parameters_size; ++i) {
+ DecodeUnsignedLeb128P1(&stream); // Parameter name.
+ }
+
+ for (;;) {
+ uint8_t opcode = *stream++;
+ switch (opcode) {
+ case DexFile::DBG_END_SEQUENCE:
+ return stream - debug_info_stream; // end of stream.
+ case DexFile::DBG_ADVANCE_PC:
+ DecodeUnsignedLeb128(&stream); // addr_diff
+ break;
+ case DexFile::DBG_ADVANCE_LINE:
+ DecodeSignedLeb128(&stream); // line_diff
+ break;
+ case DexFile::DBG_START_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ break;
+ case DexFile::DBG_START_LOCAL_EXTENDED:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ DecodeUnsignedLeb128P1(&stream); // sig_idx
+ break;
+ case DexFile::DBG_END_LOCAL:
+ case DexFile::DBG_RESTART_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ break;
+ case DexFile::DBG_SET_PROLOGUE_END:
+ case DexFile::DBG_SET_EPILOGUE_BEGIN:
+ break;
+ case DexFile::DBG_SET_FILE: {
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+}
+
EncodedValue* Collections::ReadEncodedValue(const uint8_t** data) {
const uint8_t encoded_value = *(*data)++;
const uint8_t type = encoded_value & 0x1f;
@@ -179,7 +227,7 @@
void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
- TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_, true);
+ TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_),
GetTypeId(disk_proto_id.return_type_idx_),
@@ -210,7 +258,7 @@
const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_);
const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
- TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_, false);
+ TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_);
// Annotations.
@@ -232,9 +280,8 @@
class_defs_.AddIndexedItem(class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
}
-TypeList* Collections::CreateTypeList(
- const DexFile::TypeList* dex_type_list, uint32_t offset, bool allow_empty) {
- if (dex_type_list == nullptr && !allow_empty) {
+TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
+ if (dex_type_list == nullptr) {
return nullptr;
}
// TODO: Create more efficient lookup for existing type lists.
@@ -244,7 +291,7 @@
}
}
TypeIdVector* type_vector = new TypeIdVector();
- uint32_t size = dex_type_list == nullptr ? 0 : dex_type_list->Size();
+ uint32_t size = dex_type_list->Size();
for (uint32_t index = 0; index < size; ++index) {
type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_));
}
@@ -257,6 +304,11 @@
if (static_data == nullptr) {
return nullptr;
}
+ for (std::unique_ptr<EncodedArrayItem>& existing_array_item : EncodedArrayItems()) {
+ if (existing_array_item->GetOffset() == offset) {
+ return existing_array_item.get();
+ }
+ }
uint32_t size = DecodeUnsignedLeb128(&static_data);
EncodedValueVector* values = new EncodedValueVector();
for (uint32_t i = 0; i < size; ++i) {
@@ -270,6 +322,11 @@
AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation,
uint32_t offset) {
+ for (std::unique_ptr<AnnotationItem>& existing_annotation_item : AnnotationItems()) {
+ if (existing_annotation_item->GetOffset() == offset) {
+ return existing_annotation_item.get();
+ }
+ }
uint8_t visibility = annotation->visibility_;
const uint8_t* annotation_data = annotation->annotation_;
EncodedValue* encoded_value =
@@ -284,9 +341,14 @@
AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
const DexFile::AnnotationSetItem& disk_annotations_item, uint32_t offset) {
- if (disk_annotations_item.size_ == 0) {
+ if (disk_annotations_item.size_ == 0 && offset == 0) {
return nullptr;
}
+ for (std::unique_ptr<AnnotationSetItem>& existing_anno_set_item : AnnotationSetItems()) {
+ if (existing_anno_set_item->GetOffset() == offset) {
+ return existing_anno_set_item.get();
+ }
+ }
std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) {
const DexFile::AnnotationItem* annotation =
@@ -305,6 +367,11 @@
AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
+ for (std::unique_ptr<AnnotationsDirectoryItem>& anno_dir_item : AnnotationsDirectoryItems()) {
+ if (anno_dir_item->GetOffset() == offset) {
+ return anno_dir_item.get();
+ }
+ }
const DexFile::AnnotationSetItem* class_set_item =
dex_file.GetClassAnnotationSet(disk_annotations_item);
AnnotationSetItem* class_annotation = nullptr;
@@ -367,16 +434,25 @@
ParameterAnnotation* Collections::GenerateParameterAnnotation(
const DexFile& dex_file, MethodId* method_id,
const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
- std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
- for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
- const DexFile::AnnotationSetItem* annotation_set_item =
- dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
- uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
- annotations->push_back(CreateAnnotationSetItem(dex_file, *annotation_set_item, set_offset));
+ AnnotationSetRefList* set_ref_list = nullptr;
+ for (std::unique_ptr<AnnotationSetRefList>& existing_set_ref_list : AnnotationSetRefLists()) {
+ if (existing_set_ref_list->GetOffset() == offset) {
+ set_ref_list = existing_set_ref_list.get();
+ break;
+ }
}
- AnnotationSetRefList* new_ref_list = new AnnotationSetRefList(annotations);
- annotation_set_ref_lists_.AddItem(new_ref_list, offset);
- return new ParameterAnnotation(method_id, new_ref_list);
+ if (set_ref_list == nullptr) {
+ std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
+ for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
+ const DexFile::AnnotationSetItem* annotation_set_item =
+ dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
+ uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
+ annotations->push_back(CreateAnnotationSetItem(dex_file, *annotation_set_item, set_offset));
+ }
+ set_ref_list = new AnnotationSetRefList(annotations);
+ annotation_set_ref_lists_.AddItem(set_ref_list, offset);
+ }
+ return new ParameterAnnotation(method_id, set_ref_list);
}
CodeItem* Collections::CreateCodeItem(const DexFile& dex_file,
@@ -390,7 +466,10 @@
const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item);
DebugInfoItem* debug_info = nullptr;
if (debug_info_stream != nullptr) {
- debug_info = new DebugInfoItem();
+ uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
+ uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
+ memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
+ debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer);
debug_info_items_.AddItem(debug_info, disk_code_item.debug_info_off_);
}
@@ -399,26 +478,41 @@
memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
TryItemVector* tries = nullptr;
+ CatchHandlerVector* handler_list = nullptr;
if (tries_size > 0) {
tries = new TryItemVector();
+ handler_list = new CatchHandlerVector();
for (uint32_t i = 0; i < tries_size; ++i) {
const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i);
uint32_t start_addr = disk_try_item->start_addr_;
uint16_t insn_count = disk_try_item->insn_count_;
- CatchHandlerVector* handlers = new CatchHandlerVector();
- for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
- const uint16_t type_index = it.GetHandlerTypeIndex();
- const TypeId* type_id = GetTypeIdOrNullPtr(type_index);
- handlers->push_back(std::unique_ptr<const CatchHandler>(
- new CatchHandler(type_id, it.GetHandlerAddress())));
+ uint16_t handler_off = disk_try_item->handler_off_;
+ const CatchHandler* handlers = nullptr;
+ for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
+ if (handler_off == existing_handlers->GetListOffset()) {
+ handlers = existing_handlers.get();
+ }
+ }
+ if (handlers == nullptr) {
+ bool catch_all = false;
+ TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
+ for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
+ const uint16_t type_index = it.GetHandlerTypeIndex();
+ const TypeId* type_id = GetTypeIdOrNullPtr(type_index);
+ catch_all |= type_id == nullptr;
+ addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
+ new TypeAddrPair(type_id, it.GetHandlerAddress())));
+ }
+ handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
+ handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
}
TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
tries->push_back(std::unique_ptr<const TryItem>(try_item));
}
}
// TODO: Calculate the size of the code item.
- CodeItem* code_item =
- new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries);
+ CodeItem* code_item = new CodeItem(
+ registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list);
code_items_.AddItem(code_item, offset);
return code_item;
}
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index f3d2c90..5e686d3 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -24,6 +24,7 @@
#include "dex_file-inl.h"
#include "leb128.h"
+#include "utf.h"
namespace art {
namespace dex_ir {
@@ -137,10 +138,22 @@
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<StringData>>& StringDatas() { return string_datas_.Collection(); }
std::vector<std::unique_ptr<TypeList>>& TypeLists() { return type_lists_.Collection(); }
std::vector<std::unique_ptr<EncodedArrayItem>>& EncodedArrayItems()
{ return encoded_array_items_.Collection(); }
+ std::vector<std::unique_ptr<AnnotationItem>>& AnnotationItems()
+ { return annotation_items_.Collection(); }
+ std::vector<std::unique_ptr<AnnotationSetItem>>& AnnotationSetItems()
+ { return annotation_set_items_.Collection(); }
+ std::vector<std::unique_ptr<AnnotationSetRefList>>& AnnotationSetRefLists()
+ { return annotation_set_ref_lists_.Collection(); }
+ std::vector<std::unique_ptr<AnnotationsDirectoryItem>>& AnnotationsDirectoryItems()
+ { return annotations_directory_items_.Collection(); }
+ std::vector<std::unique_ptr<DebugInfoItem>>& DebugInfoItems()
+ { return debug_info_items_.Collection(); }
+ std::vector<std::unique_ptr<CodeItem>>& CodeItems() { return code_items_.Collection(); }
+ std::vector<std::unique_ptr<ClassData>>& ClassDatas() { return class_datas_.Collection(); }
void CreateStringId(const DexFile& dex_file, uint32_t i);
void CreateTypeId(const DexFile& dex_file, uint32_t i);
@@ -149,7 +162,7 @@
void CreateMethodId(const DexFile& dex_file, uint32_t i);
void CreateClassDef(const DexFile& dex_file, uint32_t i);
- TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset, bool allow_empty);
+ TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset);
EncodedArrayItem* CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset);
AnnotationItem* CreateAnnotationItem(const DexFile::AnnotationItem* annotation, uint32_t offset);
AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file,
@@ -182,14 +195,16 @@
uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); }
uint32_t StringDatasOffset() const { return string_datas_.GetOffset(); }
uint32_t TypeListsOffset() const { return type_lists_.GetOffset(); }
- uint32_t EncodedArrayOffset() const { return encoded_array_items_.GetOffset(); }
- uint32_t AnnotationOffset() const { return annotation_items_.GetOffset(); }
- uint32_t AnnotationSetOffset() const { return annotation_set_items_.GetOffset(); }
+ uint32_t EncodedArrayItemsOffset() const { return encoded_array_items_.GetOffset(); }
+ uint32_t AnnotationItemsOffset() const { return annotation_items_.GetOffset(); }
+ uint32_t AnnotationSetItemsOffset() const { return annotation_set_items_.GetOffset(); }
uint32_t AnnotationSetRefListsOffset() const { return annotation_set_ref_lists_.GetOffset(); }
- uint32_t AnnotationsDirectoryOffset() const { return annotations_directory_items_.GetOffset(); }
- uint32_t DebugInfoOffset() const { return debug_info_items_.GetOffset(); }
+ uint32_t AnnotationsDirectoryItemsOffset() const
+ { return annotations_directory_items_.GetOffset(); }
+ uint32_t DebugInfoItemsOffset() const { return debug_info_items_.GetOffset(); }
uint32_t CodeItemsOffset() const { return code_items_.GetOffset(); }
uint32_t ClassDatasOffset() const { return class_datas_.GetOffset(); }
+ uint32_t MapItemOffset() const { return map_item_offset_; }
void SetStringIdsOffset(uint32_t new_offset) { string_ids_.SetOffset(new_offset); }
void SetTypeIdsOffset(uint32_t new_offset) { type_ids_.SetOffset(new_offset); }
@@ -199,16 +214,19 @@
void SetClassDefsOffset(uint32_t new_offset) { class_defs_.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 SetEncodedArrayOffset(uint32_t new_offset) { encoded_array_items_.SetOffset(new_offset); }
- void SetAnnotationOffset(uint32_t new_offset) { annotation_items_.SetOffset(new_offset); }
- void SetAnnotationSetOffset(uint32_t new_offset) { annotation_set_items_.SetOffset(new_offset); }
+ void SetEncodedArrayItemsOffset(uint32_t new_offset)
+ { encoded_array_items_.SetOffset(new_offset); }
+ void SetAnnotationItemsOffset(uint32_t new_offset) { annotation_items_.SetOffset(new_offset); }
+ void SetAnnotationSetItemsOffset(uint32_t new_offset)
+ { annotation_set_items_.SetOffset(new_offset); }
void SetAnnotationSetRefListsOffset(uint32_t new_offset)
{ annotation_set_ref_lists_.SetOffset(new_offset); }
- void SetAnnotationsDirectoryOffset(uint32_t new_offset)
+ void SetAnnotationsDirectoryItemsOffset(uint32_t new_offset)
{ annotations_directory_items_.SetOffset(new_offset); }
- void SetDebugInfoOffset(uint32_t new_offset) { debug_info_items_.SetOffset(new_offset); }
+ void SetDebugInfoItemsOffset(uint32_t new_offset) { debug_info_items_.SetOffset(new_offset); }
void SetCodeItemsOffset(uint32_t new_offset) { code_items_.SetOffset(new_offset); }
void SetClassDatasOffset(uint32_t new_offset) { class_datas_.SetOffset(new_offset); }
+ void SetMapItemOffset(uint32_t new_offset) { map_item_offset_ = new_offset; }
uint32_t StringIdsSize() const { return string_ids_.Size(); }
uint32_t TypeIdsSize() const { return type_ids_.Size(); }
@@ -216,15 +234,14 @@
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 StringDatasSize() const { return string_datas_.Size(); }
uint32_t TypeListsSize() const { return type_lists_.Size(); }
- uint32_t EncodedArraySize() const { return encoded_array_items_.Size(); }
- uint32_t AnnotationSize() const { return annotation_items_.Size(); }
- uint32_t AnnotationSetSize() const { return annotation_set_items_.Size(); }
+ uint32_t EncodedArrayItemsSize() const { return encoded_array_items_.Size(); }
+ uint32_t AnnotationItemsSize() const { return annotation_items_.Size(); }
+ uint32_t AnnotationSetItemsSize() const { return annotation_set_items_.Size(); }
uint32_t AnnotationSetRefListsSize() const { return annotation_set_ref_lists_.Size(); }
- uint32_t AnnotationsDirectorySize() const { return annotations_directory_items_.Size(); }
- uint32_t DebugInfoSize() const { return debug_info_items_.Size(); }
+ uint32_t AnnotationsDirectoryItemsSize() const { return annotations_directory_items_.Size(); }
+ uint32_t DebugInfoItemsSize() const { return debug_info_items_.Size(); }
uint32_t CodeItemsSize() const { return code_items_.Size(); }
uint32_t ClassDatasSize() const { return class_datas_.Size(); }
@@ -255,6 +272,8 @@
CollectionWithOffset<CodeItem> code_items_;
CollectionWithOffset<ClassData> class_datas_;
+ uint32_t map_item_offset_ = 0;
+
DISALLOW_COPY_AND_ASSIGN(Collections);
};
@@ -364,7 +383,7 @@
class StringData : public Item {
public:
explicit StringData(const char* data) : data_(strdup(data)) {
- size_ = UnsignedLeb128Size(strlen(data)) + strlen(data);
+ size_ = UnsignedLeb128Size(CountModifiedUtf8Chars(data)) + strlen(data);
}
const char* Data() const { return data_.get(); }
@@ -372,7 +391,7 @@
void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
private:
- std::unique_ptr<const char> data_;
+ UniqueCPtr<const char> data_;
DISALLOW_COPY_AND_ASSIGN(StringData);
};
@@ -442,14 +461,14 @@
const StringId* Shorty() const { return shorty_; }
const TypeId* ReturnType() const { return return_type_; }
- const TypeIdVector& Parameters() const { return *parameters_->GetTypeList(); }
+ const TypeList* Parameters() const { return parameters_; }
void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
private:
const StringId* shorty_;
const TypeId* return_type_;
- TypeList* parameters_;
+ TypeList* parameters_; // This can be nullptr.
DISALLOW_COPY_AND_ASSIGN(ProtoId);
};
@@ -533,7 +552,7 @@
private:
uint32_t access_flags_;
const MethodId* method_id_;
- const CodeItem* code_;
+ const CodeItem* code_; // This can be nullptr.
DISALLOW_COPY_AND_ASSIGN(MethodItem);
};
@@ -691,8 +710,8 @@
interfaces_(interfaces),
source_file_(source_file),
annotations_(annotations),
- static_values_(static_values),
- class_data_(class_data) { size_ = kClassDefItemSize; }
+ class_data_(class_data),
+ static_values_(static_values) { size_ = kClassDefItemSize; }
~ClassDef() OVERRIDE { }
@@ -706,8 +725,8 @@
uint32_t InterfacesOffset() { return interfaces_ == nullptr ? 0 : interfaces_->GetOffset(); }
const StringId* SourceFile() const { return source_file_; }
AnnotationsDirectoryItem* Annotations() const { return annotations_; }
- EncodedArrayItem* StaticValues() { return static_values_; }
ClassData* GetClassData() { return class_data_; }
+ EncodedArrayItem* StaticValues() { return static_values_; }
MethodItem* GenerateMethodItem(Header& header, ClassDataItemIterator& cdii);
@@ -716,19 +735,19 @@
private:
const TypeId* class_type_;
uint32_t access_flags_;
- const TypeId* superclass_;
- TypeList* interfaces_;
- const StringId* source_file_;
- AnnotationsDirectoryItem* annotations_;
- EncodedArrayItem* static_values_;
- ClassData* class_data_;
+ const TypeId* superclass_; // This can be nullptr.
+ TypeList* interfaces_; // This can be nullptr.
+ const StringId* source_file_; // This can be nullptr.
+ AnnotationsDirectoryItem* annotations_; // This can be nullptr.
+ ClassData* class_data_; // This can be nullptr.
+ EncodedArrayItem* static_values_; // This can be nullptr.
DISALLOW_COPY_AND_ASSIGN(ClassDef);
};
-class CatchHandler {
+class TypeAddrPair {
public:
- CatchHandler(const TypeId* type_id, uint32_t address) : type_id_(type_id), address_(address) { }
+ TypeAddrPair(const TypeId* type_id, uint32_t address) : type_id_(type_id), address_(address) { }
const TypeId* GetTypeId() const { return type_id_; }
uint32_t GetAddress() const { return address_; }
@@ -737,6 +756,25 @@
const TypeId* type_id_;
uint32_t address_;
+ DISALLOW_COPY_AND_ASSIGN(TypeAddrPair);
+};
+
+using TypeAddrPairVector = std::vector<std::unique_ptr<const TypeAddrPair>>;
+
+class CatchHandler {
+ public:
+ explicit CatchHandler(bool catch_all, uint16_t list_offset, TypeAddrPairVector* handlers)
+ : catch_all_(catch_all), list_offset_(list_offset), handlers_(handlers) { }
+
+ bool HasCatchAll() const { return catch_all_; }
+ uint16_t GetListOffset() const { return list_offset_; }
+ TypeAddrPairVector* GetHandlers() const { return handlers_.get(); }
+
+ private:
+ bool catch_all_;
+ uint16_t list_offset_;
+ std::unique_ptr<TypeAddrPairVector> handlers_;
+
DISALLOW_COPY_AND_ASSIGN(CatchHandler);
};
@@ -744,20 +782,20 @@
class TryItem : public Item {
public:
- TryItem(uint32_t start_addr, uint16_t insn_count, CatchHandlerVector* handlers)
+ TryItem(uint32_t start_addr, uint16_t insn_count, const CatchHandler* handlers)
: start_addr_(start_addr), insn_count_(insn_count), handlers_(handlers) { }
~TryItem() OVERRIDE { }
uint32_t StartAddr() const { return start_addr_; }
uint16_t InsnCount() const { return insn_count_; }
- const CatchHandlerVector& GetHandlers() const { return *handlers_.get(); }
+ const CatchHandler* GetHandlers() const { return handlers_; }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
uint32_t start_addr_;
uint16_t insn_count_;
- std::unique_ptr<CatchHandlerVector> handlers_;
+ const CatchHandler* handlers_;
DISALLOW_COPY_AND_ASSIGN(TryItem);
};
@@ -772,14 +810,16 @@
DebugInfoItem* debug_info,
uint32_t insns_size,
uint16_t* insns,
- TryItemVector* tries)
+ TryItemVector* tries,
+ CatchHandlerVector* handlers)
: registers_size_(registers_size),
ins_size_(ins_size),
outs_size_(outs_size),
debug_info_(debug_info),
insns_size_(insns_size),
insns_(insns),
- tries_(tries) { }
+ tries_(tries),
+ handlers_(handlers) { }
~CodeItem() OVERRIDE { }
@@ -791,6 +831,7 @@
uint32_t InsnsSize() const { return insns_size_; }
uint16_t* Insns() const { return insns_.get(); }
TryItemVector* Tries() const { return tries_.get(); }
+ CatchHandlerVector* Handlers() const { return handlers_.get(); }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
@@ -798,10 +839,11 @@
uint16_t registers_size_;
uint16_t ins_size_;
uint16_t outs_size_;
- DebugInfoItem* debug_info_;
+ DebugInfoItem* debug_info_; // This can be nullptr.
uint32_t insns_size_;
std::unique_ptr<uint16_t[]> insns_;
- std::unique_ptr<TryItemVector> tries_;
+ std::unique_ptr<TryItemVector> tries_; // This can be nullptr.
+ std::unique_ptr<CatchHandlerVector> handlers_; // This can be nullptr.
DISALLOW_COPY_AND_ASSIGN(CodeItem);
};
@@ -841,12 +883,19 @@
class DebugInfoItem : public Item {
public:
- DebugInfoItem() = default;
+ DebugInfoItem(uint32_t debug_info_size, uint8_t* debug_info)
+ : debug_info_size_(debug_info_size), debug_info_(debug_info) { }
+
+ uint32_t GetDebugInfoSize() const { return debug_info_size_; }
+ uint8_t* GetDebugInfo() const { return debug_info_.get(); }
PositionInfoVector& GetPositionInfo() { return positions_; }
LocalInfoVector& GetLocalInfo() { return locals_; }
private:
+ uint32_t debug_info_size_;
+ std::unique_ptr<uint8_t[]> debug_info_;
+
PositionInfoVector positions_;
LocalInfoVector locals_;
@@ -899,7 +948,7 @@
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
- std::unique_ptr<std::vector<AnnotationSetItem*>> items_;
+ std::unique_ptr<std::vector<AnnotationSetItem*>> items_; // Elements of vector can be nullptr.
DISALLOW_COPY_AND_ASSIGN(AnnotationSetRefList);
};
@@ -974,10 +1023,10 @@
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
- AnnotationSetItem* class_annotation_;
- std::unique_ptr<FieldAnnotationVector> field_annotations_;
- std::unique_ptr<MethodAnnotationVector> method_annotations_;
- std::unique_ptr<ParameterAnnotationVector> parameter_annotations_;
+ AnnotationSetItem* class_annotation_; // This can be nullptr.
+ std::unique_ptr<FieldAnnotationVector> field_annotations_; // This can be nullptr.
+ std::unique_ptr<MethodAnnotationVector> method_annotations_; // This can be nullptr.
+ std::unique_ptr<ParameterAnnotationVector> parameter_annotations_; // This can be nullptr.
DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem);
};
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index 599f48b..68ff2a2 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -70,6 +70,8 @@
for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
collections.CreateClassDef(dex_file, i);
}
+ // MapItem.
+ collections.SetMapItemOffset(disk_header.map_off_);
CheckAndSetRemainingOffsets(dex_file, &collections);
@@ -124,7 +126,7 @@
collections->SetAnnotationSetRefListsOffset(item->offset_);
break;
case DexFile::kDexTypeAnnotationSetItem:
- collections->SetAnnotationSetOffset(item->offset_);
+ collections->SetAnnotationSetItemsOffset(item->offset_);
break;
case DexFile::kDexTypeClassDataItem:
collections->SetClassDatasOffset(item->offset_);
@@ -136,16 +138,16 @@
collections->SetStringDatasOffset(item->offset_);
break;
case DexFile::kDexTypeDebugInfoItem:
- collections->SetDebugInfoOffset(item->offset_);
+ collections->SetDebugInfoItemsOffset(item->offset_);
break;
case DexFile::kDexTypeAnnotationItem:
- collections->SetAnnotationOffset(item->offset_);
+ collections->SetAnnotationItemsOffset(item->offset_);
break;
case DexFile::kDexTypeEncodedArrayItem:
- collections->SetEncodedArrayOffset(item->offset_);
+ collections->SetEncodedArrayItemsOffset(item->offset_);
break;
case DexFile::kDexTypeAnnotationsDirectoryItem:
- collections->SetAnnotationsDirectoryOffset(item->offset_);
+ collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
break;
default:
LOG(ERROR) << "Unknown map list item type.";
diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc
index be7bade..46dff5f 100644
--- a/dexlayout/dex_visualize.cc
+++ b/dexlayout/dex_visualize.cc
@@ -87,18 +87,18 @@
}, {
"EncArr",
DexFile::kDexTypeEncodedArrayItem,
- &dex_ir::Collections::EncodedArraySize,
- &dex_ir::Collections::EncodedArrayOffset
+ &dex_ir::Collections::EncodedArrayItemsSize,
+ &dex_ir::Collections::EncodedArrayItemsOffset
}, {
"Annotation",
DexFile::kDexTypeAnnotationItem,
- &dex_ir::Collections::AnnotationSize,
- &dex_ir::Collections::AnnotationOffset
+ &dex_ir::Collections::AnnotationItemsSize,
+ &dex_ir::Collections::AnnotationItemsOffset
}, {
"AnnoSet",
DexFile::kDexTypeAnnotationSetItem,
- &dex_ir::Collections::AnnotationSetSize,
- &dex_ir::Collections::AnnotationSetOffset
+ &dex_ir::Collections::AnnotationSetItemsSize,
+ &dex_ir::Collections::AnnotationSetItemsOffset
}, {
"AnnoSetRL",
DexFile::kDexTypeAnnotationSetRefList,
@@ -107,13 +107,13 @@
}, {
"AnnoDir",
DexFile::kDexTypeAnnotationsDirectoryItem,
- &dex_ir::Collections::AnnotationsDirectorySize,
- &dex_ir::Collections::AnnotationsDirectoryOffset
+ &dex_ir::Collections::AnnotationsDirectoryItemsSize,
+ &dex_ir::Collections::AnnotationsDirectoryItemsOffset
}, {
"DebugInfo",
DexFile::kDexTypeDebugInfoItem,
- &dex_ir::Collections::DebugInfoSize,
- &dex_ir::Collections::DebugInfoOffset
+ &dex_ir::Collections::DebugInfoItemsSize,
+ &dex_ir::Collections::DebugInfoItemsOffset
}, {
"CodeItem",
DexFile::kDexTypeCodeItem,
@@ -244,9 +244,11 @@
return;
}
DumpStringId(proto_id->Shorty(), class_index);
- const dex_ir::TypeIdVector& parameters = proto_id->Parameters();
- for (const dex_ir::TypeId* t : parameters) {
- DumpTypeId(t, class_index);
+ const dex_ir::TypeList* type_list = proto_id->Parameters();
+ if (type_list != nullptr) {
+ for (const dex_ir::TypeId* t : *type_list->GetTypeList()) {
+ DumpTypeId(t, class_index);
+ }
}
DumpTypeId(proto_id->ReturnType(), class_index);
}
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
new file mode 100644
index 0000000..dba5da0
--- /dev/null
+++ b/dexlayout/dex_writer.cc
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Header file of an in-memory representation of DEX files.
+ */
+
+#include <stdint.h>
+
+#include <queue>
+#include <vector>
+
+#include "dex_writer.h"
+#include "utf.h"
+
+namespace art {
+
+size_t EncodeIntValue(int32_t value, uint8_t* buffer) {
+ size_t length = 0;
+ if (value >= 0) {
+ while (value > 0x7f) {
+ buffer[length++] = static_cast<uint8_t>(value);
+ value >>= 8;
+ }
+ } else {
+ while (value < -0x80) {
+ buffer[length++] = static_cast<uint8_t>(value);
+ value >>= 8;
+ }
+ }
+ buffer[length++] = static_cast<uint8_t>(value);
+ return length;
+}
+
+size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) {
+ size_t length = 0;
+ do {
+ buffer[length++] = static_cast<uint8_t>(value);
+ value >>= 8;
+ } while (value != 0);
+ return length;
+}
+
+size_t EncodeLongValue(int64_t value, uint8_t* buffer) {
+ size_t length = 0;
+ if (value >= 0) {
+ while (value > 0x7f) {
+ buffer[length++] = static_cast<uint8_t>(value);
+ value >>= 8;
+ }
+ } else {
+ while (value < -0x80) {
+ buffer[length++] = static_cast<uint8_t>(value);
+ value >>= 8;
+ }
+ }
+ buffer[length++] = static_cast<uint8_t>(value);
+ return length;
+}
+
+union FloatUnion {
+ float f_;
+ uint32_t i_;
+};
+
+size_t EncodeFloatValue(float value, uint8_t* buffer) {
+ FloatUnion float_union;
+ float_union.f_ = value;
+ uint32_t int_value = float_union.i_;
+ size_t index = 3;
+ do {
+ buffer[index--] = int_value >> 24;
+ int_value <<= 8;
+ } while (int_value != 0);
+ return 3 - index;
+}
+
+union DoubleUnion {
+ double d_;
+ uint64_t l_;
+};
+
+size_t EncodeDoubleValue(double value, uint8_t* buffer) {
+ DoubleUnion double_union;
+ double_union.d_ = value;
+ uint64_t long_value = double_union.l_;
+ size_t index = 7;
+ do {
+ buffer[index--] = long_value >> 56;
+ long_value <<= 8;
+ } while (long_value != 0);
+ return 7 - index;
+}
+
+size_t DexWriter::Write(const void* buffer, size_t length, size_t offset) {
+ return dex_file_->PwriteFully(buffer, length, offset) ? length : 0;
+}
+
+size_t DexWriter::WriteSleb128(uint32_t value, size_t offset) {
+ uint8_t buffer[8];
+ EncodeSignedLeb128(buffer, value);
+ return Write(buffer, SignedLeb128Size(value), offset);
+}
+
+size_t DexWriter::WriteUleb128(uint32_t value, size_t offset) {
+ uint8_t buffer[8];
+ EncodeUnsignedLeb128(buffer, value);
+ return Write(buffer, UnsignedLeb128Size(value), offset);
+}
+
+size_t DexWriter::WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) {
+ size_t original_offset = offset;
+ size_t start = 0;
+ size_t length;
+ uint8_t buffer[8];
+ int8_t type = encoded_value->Type();
+ switch (type) {
+ case DexFile::kDexAnnotationByte:
+ length = EncodeIntValue(encoded_value->GetByte(), buffer);
+ break;
+ case DexFile::kDexAnnotationShort:
+ length = EncodeIntValue(encoded_value->GetShort(), buffer);
+ break;
+ case DexFile::kDexAnnotationChar:
+ length = EncodeUIntValue(encoded_value->GetChar(), buffer);
+ break;
+ case DexFile::kDexAnnotationInt:
+ length = EncodeIntValue(encoded_value->GetInt(), buffer);
+ break;
+ case DexFile::kDexAnnotationLong:
+ length = EncodeLongValue(encoded_value->GetLong(), buffer);
+ break;
+ case DexFile::kDexAnnotationFloat:
+ length = EncodeFloatValue(encoded_value->GetFloat(), buffer);
+ start = 4 - length;
+ break;
+ case DexFile::kDexAnnotationDouble:
+ length = EncodeDoubleValue(encoded_value->GetDouble(), buffer);
+ start = 8 - length;
+ break;
+ case DexFile::kDexAnnotationString:
+ length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
+ break;
+ case DexFile::kDexAnnotationType:
+ length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer);
+ break;
+ case DexFile::kDexAnnotationField:
+ case DexFile::kDexAnnotationEnum:
+ length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer);
+ break;
+ case DexFile::kDexAnnotationMethod:
+ length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer);
+ break;
+ case DexFile::kDexAnnotationArray:
+ offset += WriteEncodedValueHeader(type, 0, offset);
+ offset += WriteEncodedArray(encoded_value->GetEncodedArray()->GetEncodedValues(), offset);
+ return offset - original_offset;
+ case DexFile::kDexAnnotationAnnotation:
+ offset += WriteEncodedValueHeader(type, 0, offset);
+ offset += WriteEncodedAnnotation(encoded_value->GetEncodedAnnotation(), offset);
+ return offset - original_offset;
+ case DexFile::kDexAnnotationNull:
+ return WriteEncodedValueHeader(type, 0, offset);
+ case DexFile::kDexAnnotationBoolean:
+ return WriteEncodedValueHeader(type, encoded_value->GetBoolean() ? 1 : 0, offset);
+ default:
+ return 0;
+ }
+ offset += WriteEncodedValueHeader(type, length - 1, offset);
+ offset += Write(buffer + start, length, offset);
+ return offset - original_offset;
+}
+
+size_t DexWriter::WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) {
+ uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) };
+ return Write(buffer, sizeof(uint8_t), offset);
+}
+
+size_t DexWriter::WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) {
+ size_t original_offset = offset;
+ offset += WriteUleb128(values->size(), offset);
+ for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) {
+ offset += WriteEncodedValue(value.get(), offset);
+ }
+ return offset - original_offset;
+}
+
+size_t DexWriter::WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) {
+ size_t original_offset = offset;
+ offset += WriteUleb128(annotation->GetType()->GetIndex(), offset);
+ offset += WriteUleb128(annotation->GetAnnotationElements()->size(), offset);
+ for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element :
+ *annotation->GetAnnotationElements()) {
+ offset += WriteUleb128(annotation_element->GetName()->GetIndex(), offset);
+ offset += WriteEncodedValue(annotation_element->GetValue(), offset);
+ }
+ return offset - original_offset;
+}
+
+size_t DexWriter::WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) {
+ size_t original_offset = offset;
+ uint32_t prev_index = 0;
+ for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) {
+ uint32_t index = field->GetFieldId()->GetIndex();
+ offset += WriteUleb128(index - prev_index, offset);
+ offset += WriteUleb128(field->GetAccessFlags(), offset);
+ prev_index = index;
+ }
+ return offset - original_offset;
+}
+
+size_t DexWriter::WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) {
+ size_t original_offset = offset;
+ uint32_t prev_index = 0;
+ for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) {
+ uint32_t index = method->GetMethodId()->GetIndex();
+ uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset();
+ offset += WriteUleb128(index - prev_index, offset);
+ offset += WriteUleb128(method->GetAccessFlags(), offset);
+ offset += WriteUleb128(code_off, offset);
+ prev_index = index;
+ }
+ return offset - original_offset;
+}
+
+void DexWriter::WriteStrings() {
+ uint32_t string_data_off[1];
+ for (std::unique_ptr<dex_ir::StringId>& string_id : header_.GetCollections().StringIds()) {
+ string_data_off[0] = string_id->DataItem()->GetOffset();
+ Write(string_data_off, string_id->GetSize(), string_id->GetOffset());
+ }
+
+ for (std::unique_ptr<dex_ir::StringData>& string_data : header_.GetCollections().StringDatas()) {
+ uint32_t offset = string_data->GetOffset();
+ offset += WriteUleb128(CountModifiedUtf8Chars(string_data->Data()), offset);
+ Write(string_data->Data(), strlen(string_data->Data()), offset);
+ }
+}
+
+void DexWriter::WriteTypes() {
+ uint32_t descriptor_idx[1];
+ for (std::unique_ptr<dex_ir::TypeId>& type_id : header_.GetCollections().TypeIds()) {
+ descriptor_idx[0] = type_id->GetStringId()->GetIndex();
+ Write(descriptor_idx, type_id->GetSize(), type_id->GetOffset());
+ }
+}
+
+void DexWriter::WriteTypeLists() {
+ uint32_t size[1];
+ uint16_t list[1];
+ for (std::unique_ptr<dex_ir::TypeList>& type_list : header_.GetCollections().TypeLists()) {
+ size[0] = type_list->GetTypeList()->size();
+ uint32_t offset = type_list->GetOffset();
+ offset += Write(size, sizeof(uint32_t), offset);
+ for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
+ list[0] = type_id->GetIndex();
+ offset += Write(list, sizeof(uint16_t), offset);
+ }
+ }
+}
+
+void DexWriter::WriteProtos() {
+ uint32_t buffer[3];
+ for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_.GetCollections().ProtoIds()) {
+ buffer[0] = proto_id->Shorty()->GetIndex();
+ buffer[1] = proto_id->ReturnType()->GetIndex();
+ buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset();
+ Write(buffer, proto_id->GetSize(), proto_id->GetOffset());
+ }
+}
+
+void DexWriter::WriteFields() {
+ uint16_t buffer[4];
+ for (std::unique_ptr<dex_ir::FieldId>& field_id : header_.GetCollections().FieldIds()) {
+ buffer[0] = field_id->Class()->GetIndex();
+ buffer[1] = field_id->Type()->GetIndex();
+ buffer[2] = field_id->Name()->GetIndex();
+ buffer[3] = field_id->Name()->GetIndex() >> 16;
+ Write(buffer, field_id->GetSize(), field_id->GetOffset());
+ }
+}
+
+void DexWriter::WriteMethods() {
+ uint16_t buffer[4];
+ for (std::unique_ptr<dex_ir::MethodId>& method_id : header_.GetCollections().MethodIds()) {
+ buffer[0] = method_id->Class()->GetIndex();
+ buffer[1] = method_id->Proto()->GetIndex();
+ buffer[2] = method_id->Name()->GetIndex();
+ buffer[3] = method_id->Name()->GetIndex() >> 16;
+ Write(buffer, method_id->GetSize(), method_id->GetOffset());
+ }
+}
+
+void DexWriter::WriteEncodedArrays() {
+ for (std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array :
+ header_.GetCollections().EncodedArrayItems()) {
+ WriteEncodedArray(encoded_array->GetEncodedValues(), encoded_array->GetOffset());
+ }
+}
+
+void DexWriter::WriteAnnotations() {
+ uint8_t visibility[1];
+ for (std::unique_ptr<dex_ir::AnnotationItem>& annotation :
+ header_.GetCollections().AnnotationItems()) {
+ visibility[0] = annotation->GetVisibility();
+ size_t offset = annotation->GetOffset();
+ offset += Write(visibility, sizeof(uint8_t), offset);
+ WriteEncodedAnnotation(annotation->GetAnnotation(), offset);
+ }
+}
+
+void DexWriter::WriteAnnotationSets() {
+ uint32_t size[1];
+ uint32_t annotation_off[1];
+ for (std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set :
+ header_.GetCollections().AnnotationSetItems()) {
+ size[0] = annotation_set->GetItems()->size();
+ size_t offset = annotation_set->GetOffset();
+ offset += Write(size, sizeof(uint32_t), offset);
+ for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) {
+ annotation_off[0] = annotation->GetOffset();
+ offset += Write(annotation_off, sizeof(uint32_t), offset);
+ }
+ }
+}
+
+void DexWriter::WriteAnnotationSetRefs() {
+ uint32_t size[1];
+ uint32_t annotations_off[1];
+ for (std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref :
+ header_.GetCollections().AnnotationSetRefLists()) {
+ size[0] = annotation_set_ref->GetItems()->size();
+ size_t offset = annotation_set_ref->GetOffset();
+ offset += Write(size, sizeof(uint32_t), offset);
+ for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) {
+ annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset();
+ offset += Write(annotations_off, sizeof(uint32_t), offset);
+ }
+ }
+}
+
+void DexWriter::WriteAnnotationsDirectories() {
+ uint32_t directory_buffer[4];
+ uint32_t annotation_buffer[2];
+ for (std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory :
+ header_.GetCollections().AnnotationsDirectoryItems()) {
+ directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
+ annotations_directory->GetClassAnnotation()->GetOffset();
+ directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 :
+ annotations_directory->GetFieldAnnotations()->size();
+ directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 :
+ annotations_directory->GetMethodAnnotations()->size();
+ directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 :
+ annotations_directory->GetParameterAnnotations()->size();
+ uint32_t offset = annotations_directory->GetOffset();
+ offset += Write(directory_buffer, 4 * sizeof(uint32_t), offset);
+ if (annotations_directory->GetFieldAnnotations() != nullptr) {
+ for (std::unique_ptr<dex_ir::FieldAnnotation>& field :
+ *annotations_directory->GetFieldAnnotations()) {
+ annotation_buffer[0] = field->GetFieldId()->GetIndex();
+ annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset();
+ offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
+ }
+ }
+ if (annotations_directory->GetMethodAnnotations() != nullptr) {
+ for (std::unique_ptr<dex_ir::MethodAnnotation>& method :
+ *annotations_directory->GetMethodAnnotations()) {
+ annotation_buffer[0] = method->GetMethodId()->GetIndex();
+ annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset();
+ offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
+ }
+ }
+ if (annotations_directory->GetParameterAnnotations() != nullptr) {
+ for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter :
+ *annotations_directory->GetParameterAnnotations()) {
+ annotation_buffer[0] = parameter->GetMethodId()->GetIndex();
+ annotation_buffer[1] = parameter->GetAnnotations()->GetOffset();
+ offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
+ }
+ }
+ }
+}
+
+void DexWriter::WriteDebugInfoItems() {
+ for (std::unique_ptr<dex_ir::DebugInfoItem>& info : header_.GetCollections().DebugInfoItems()) {
+ Write(info->GetDebugInfo(), info->GetDebugInfoSize(), info->GetOffset());
+ }
+}
+
+void DexWriter::WriteCodeItems() {
+ uint16_t uint16_buffer[4];
+ uint32_t uint32_buffer[2];
+ for (std::unique_ptr<dex_ir::CodeItem>& code_item : header_.GetCollections().CodeItems()) {
+ uint16_buffer[0] = code_item->RegistersSize();
+ uint16_buffer[1] = code_item->InsSize();
+ uint16_buffer[2] = code_item->OutsSize();
+ uint16_buffer[3] = code_item->TriesSize();
+ uint32_buffer[0] = code_item->DebugInfo() == nullptr ? 0 : code_item->DebugInfo()->GetOffset();
+ uint32_buffer[1] = code_item->InsnsSize();
+ size_t offset = code_item->GetOffset();
+ offset += Write(uint16_buffer, 4 * sizeof(uint16_t), offset);
+ offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
+ offset += Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t), offset);
+ if (code_item->TriesSize() != 0) {
+ if (code_item->InsnsSize() % 2 != 0) {
+ uint16_t padding[1] = { 0 };
+ offset += Write(padding, sizeof(uint16_t), offset);
+ }
+ uint32_t start_addr[1];
+ uint16_t insn_count_and_handler_off[2];
+ for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) {
+ start_addr[0] = try_item->StartAddr();
+ insn_count_and_handler_off[0] = try_item->InsnCount();
+ insn_count_and_handler_off[1] = try_item->GetHandlers()->GetListOffset();
+ offset += Write(start_addr, sizeof(uint32_t), offset);
+ offset += Write(insn_count_and_handler_off, 2 * sizeof(uint16_t), offset);
+ }
+ // Leave offset pointing to the end of the try items.
+ WriteUleb128(code_item->Handlers()->size(), offset);
+ for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) {
+ size_t list_offset = offset + handlers->GetListOffset();
+ uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 :
+ handlers->GetHandlers()->size();
+ list_offset += WriteSleb128(size, list_offset);
+ for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) {
+ if (handler->GetTypeId() != nullptr) {
+ list_offset += WriteUleb128(handler->GetTypeId()->GetIndex(), list_offset);
+ }
+ list_offset += WriteUleb128(handler->GetAddress(), list_offset);
+ }
+ }
+ }
+ }
+}
+
+void DexWriter::WriteClasses() {
+ uint32_t class_def_buffer[8];
+ for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_.GetCollections().ClassDefs()) {
+ class_def_buffer[0] = class_def->ClassType()->GetIndex();
+ class_def_buffer[1] = class_def->GetAccessFlags();
+ class_def_buffer[2] = class_def->Superclass() == nullptr ? DexFile::kDexNoIndex :
+ class_def->Superclass()->GetIndex();
+ class_def_buffer[3] = class_def->InterfacesOffset();
+ class_def_buffer[4] = class_def->SourceFile() == nullptr ? DexFile::kDexNoIndex :
+ class_def->SourceFile()->GetIndex();
+ class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 :
+ class_def->Annotations()->GetOffset();
+ class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 :
+ class_def->GetClassData()->GetOffset();
+ class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 :
+ class_def->StaticValues()->GetOffset();
+ size_t offset = class_def->GetOffset();
+ Write(class_def_buffer, class_def->GetSize(), offset);
+ }
+
+ for (std::unique_ptr<dex_ir::ClassData>& class_data : header_.GetCollections().ClassDatas()) {
+ size_t offset = class_data->GetOffset();
+ offset += WriteUleb128(class_data->StaticFields()->size(), offset);
+ offset += WriteUleb128(class_data->InstanceFields()->size(), offset);
+ offset += WriteUleb128(class_data->DirectMethods()->size(), offset);
+ offset += WriteUleb128(class_data->VirtualMethods()->size(), offset);
+ offset += WriteEncodedFields(class_data->StaticFields(), offset);
+ offset += WriteEncodedFields(class_data->InstanceFields(), offset);
+ offset += WriteEncodedMethods(class_data->DirectMethods(), offset);
+ offset += WriteEncodedMethods(class_data->VirtualMethods(), offset);
+ }
+}
+
+struct MapItemContainer {
+ MapItemContainer(uint32_t type, uint32_t size, uint32_t offset)
+ : type_(type), size_(size), offset_(offset) { }
+
+ bool operator<(const MapItemContainer& other) const {
+ return offset_ > other.offset_;
+ }
+
+ uint32_t type_;
+ uint32_t size_;
+ uint32_t offset_;
+};
+
+void DexWriter::WriteMapItem() {
+ dex_ir::Collections& collection = header_.GetCollections();
+ std::priority_queue<MapItemContainer> queue;
+
+ // Header and index section.
+ queue.push(MapItemContainer(DexFile::kDexTypeHeaderItem, 1, 0));
+ if (collection.StringIdsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeStringIdItem, collection.StringIdsSize(),
+ collection.StringIdsOffset()));
+ }
+ if (collection.TypeIdsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeTypeIdItem, collection.TypeIdsSize(),
+ collection.TypeIdsOffset()));
+ }
+ if (collection.ProtoIdsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeProtoIdItem, collection.ProtoIdsSize(),
+ collection.ProtoIdsOffset()));
+ }
+ if (collection.FieldIdsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeFieldIdItem, collection.FieldIdsSize(),
+ collection.FieldIdsOffset()));
+ }
+ if (collection.MethodIdsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeMethodIdItem, collection.MethodIdsSize(),
+ collection.MethodIdsOffset()));
+ }
+ if (collection.ClassDefsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeClassDefItem, collection.ClassDefsSize(),
+ collection.ClassDefsOffset()));
+ }
+
+ // Data section.
+ queue.push(MapItemContainer(DexFile::kDexTypeMapList, 1, collection.MapItemOffset()));
+ if (collection.TypeListsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeTypeList, collection.TypeListsSize(),
+ collection.TypeListsOffset()));
+ }
+ if (collection.AnnotationSetRefListsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetRefList,
+ collection.AnnotationSetRefListsSize(), collection.AnnotationSetRefListsOffset()));
+ }
+ if (collection.AnnotationSetItemsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetItem,
+ collection.AnnotationSetItemsSize(), collection.AnnotationSetItemsOffset()));
+ }
+ if (collection.ClassDatasSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeClassDataItem, collection.ClassDatasSize(),
+ collection.ClassDatasOffset()));
+ }
+ if (collection.CodeItemsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeCodeItem, collection.CodeItemsSize(),
+ collection.CodeItemsOffset()));
+ }
+ if (collection.StringDatasSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeStringDataItem, collection.StringDatasSize(),
+ collection.StringDatasOffset()));
+ }
+ if (collection.DebugInfoItemsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeDebugInfoItem, collection.DebugInfoItemsSize(),
+ collection.DebugInfoItemsOffset()));
+ }
+ if (collection.AnnotationItemsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeAnnotationItem, collection.AnnotationItemsSize(),
+ collection.AnnotationItemsOffset()));
+ }
+ if (collection.EncodedArrayItemsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeEncodedArrayItem,
+ collection.EncodedArrayItemsSize(), collection.EncodedArrayItemsOffset()));
+ }
+ if (collection.AnnotationsDirectoryItemsSize() != 0) {
+ queue.push(MapItemContainer(DexFile::kDexTypeAnnotationsDirectoryItem,
+ collection.AnnotationsDirectoryItemsSize(), collection.AnnotationsDirectoryItemsOffset()));
+ }
+
+ uint32_t offset = collection.MapItemOffset();
+ uint16_t uint16_buffer[2];
+ uint32_t uint32_buffer[2];
+ uint16_buffer[1] = 0;
+ uint32_buffer[0] = queue.size();
+ offset += Write(uint32_buffer, sizeof(uint32_t), offset);
+ while (!queue.empty()) {
+ const MapItemContainer& map_item = queue.top();
+ uint16_buffer[0] = map_item.type_;
+ uint32_buffer[0] = map_item.size_;
+ uint32_buffer[1] = map_item.offset_;
+ offset += Write(uint16_buffer, 2 * sizeof(uint16_t), offset);
+ offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
+ queue.pop();
+ }
+}
+
+void DexWriter::WriteHeader() {
+ uint32_t buffer[20];
+ dex_ir::Collections& collections = header_.GetCollections();
+ size_t offset = 0;
+ offset += Write(header_.Magic(), 8 * sizeof(uint8_t), offset);
+ buffer[0] = header_.Checksum();
+ offset += Write(buffer, sizeof(uint32_t), offset);
+ offset += Write(header_.Signature(), 20 * sizeof(uint8_t), offset);
+ uint32_t file_size = header_.FileSize();
+ buffer[0] = file_size;
+ buffer[1] = header_.GetSize();
+ buffer[2] = header_.EndianTag();
+ buffer[3] = header_.LinkSize();
+ buffer[4] = header_.LinkOffset();
+ buffer[5] = collections.MapItemOffset();
+ buffer[6] = collections.StringIdsSize();
+ buffer[7] = collections.StringIdsOffset();
+ buffer[8] = collections.TypeIdsSize();
+ buffer[9] = collections.TypeIdsOffset();
+ buffer[10] = collections.ProtoIdsSize();
+ buffer[11] = collections.ProtoIdsOffset();
+ buffer[12] = collections.FieldIdsSize();
+ buffer[13] = collections.FieldIdsOffset();
+ buffer[14] = collections.MethodIdsSize();
+ buffer[15] = collections.MethodIdsOffset();
+ uint32_t class_defs_size = collections.ClassDefsSize();
+ 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;
+ Write(buffer, 20 * sizeof(uint32_t), offset);
+}
+
+void DexWriter::WriteFile() {
+ if (dex_file_.get() == nullptr) {
+ fprintf(stderr, "Can't open output dex file\n");
+ return;
+ }
+
+ WriteStrings();
+ WriteTypes();
+ WriteTypeLists();
+ WriteProtos();
+ WriteFields();
+ WriteMethods();
+ WriteEncodedArrays();
+ WriteAnnotations();
+ WriteAnnotationSets();
+ WriteAnnotationSetRefs();
+ WriteAnnotationsDirectories();
+ WriteDebugInfoItems();
+ WriteCodeItems();
+ WriteClasses();
+ WriteMapItem();
+ WriteHeader();
+}
+
+void DexWriter::OutputDexFile(dex_ir::Header& header, const char* file_name) {
+ (new DexWriter(header, file_name))->WriteFile();
+}
+
+} // namespace art
diff --git a/dexlayout/dex_writer.h b/dexlayout/dex_writer.h
new file mode 100644
index 0000000..9104295
--- /dev/null
+++ b/dexlayout/dex_writer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Header file of an in-memory representation of DEX files.
+ */
+
+#ifndef ART_DEXLAYOUT_DEX_WRITER_H_
+#define ART_DEXLAYOUT_DEX_WRITER_H_
+
+#include "base/unix_file/fd_file.h"
+#include "dex_ir.h"
+#include "os.h"
+
+namespace art {
+
+class DexWriter {
+ public:
+ DexWriter(dex_ir::Header& header, const char* file_name) : header_(header),
+ dex_file_(OS::CreateEmptyFileWriteOnly(file_name)) { }
+
+ static void OutputDexFile(dex_ir::Header& header, const char* file_name);
+
+ private:
+ void WriteFile();
+
+ size_t Write(const void* buffer, size_t length, size_t offset);
+ size_t WriteSleb128(uint32_t value, size_t offset);
+ size_t WriteUleb128(uint32_t value, size_t offset);
+ size_t WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset);
+ size_t WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset);
+ size_t WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset);
+ size_t WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset);
+ size_t WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset);
+ size_t WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset);
+
+ void WriteStrings();
+ void WriteTypes();
+ void WriteTypeLists();
+ void WriteProtos();
+ void WriteFields();
+ void WriteMethods();
+ void WriteEncodedArrays();
+ void WriteAnnotations();
+ void WriteAnnotationSets();
+ void WriteAnnotationSetRefs();
+ void WriteAnnotationsDirectories();
+ void WriteDebugInfoItems();
+ void WriteCodeItems();
+ void WriteClasses();
+ void WriteMapItem();
+ void WriteHeader();
+
+ dex_ir::Header& header_;
+ std::unique_ptr<File> dex_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(DexWriter);
+};
+
+
+} // namespace art
+
+#endif // ART_DEXLAYOUT_DEX_WRITER_H_
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index e614137..a9ae55f 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -30,11 +30,11 @@
#include <sstream>
#include <vector>
-#include "base/unix_file/fd_file.h"
#include "dex_ir_builder.h"
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
#include "dex_visualize.h"
+#include "dex_writer.h"
#include "jit/offline_profiling_info.h"
#include "os.h"
#include "utils.h"
@@ -251,10 +251,12 @@
return "<no signature>";
}
- const std::vector<const dex_ir::TypeId*>& params = proto->Parameters();
std::string result("(");
- for (uint32_t i = 0; i < params.size(); ++i) {
- result += params[i]->GetStringId()->Data();
+ const dex_ir::TypeList* type_list = proto->Parameters();
+ if (type_list != nullptr) {
+ for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
+ result += type_id->GetStringId()->Data();
+ }
}
result += ")";
result += proto->ReturnType()->GetStringId()->Data();
@@ -673,7 +675,7 @@
const uint32_t start = try_item->StartAddr();
const uint32_t end = start + try_item->InsnCount();
fprintf(out_file_, " 0x%04x - 0x%04x\n", start, end);
- for (auto& handler : try_item->GetHandlers()) {
+ for (auto& handler : *try_item->GetHandlers()->GetHandlers()) {
const dex_ir::TypeId* type_id = handler->GetTypeId();
const char* descriptor = (type_id == nullptr) ? "<any>" : type_id->GetStringId()->Data();
fprintf(out_file_, " %s -> 0x%04x\n", descriptor, handler->GetAddress());
@@ -1502,96 +1504,6 @@
}
/*
-static uint32_t GetDataSectionOffset(dex_ir::Header& header) {
- return dex_ir::Header::ItemSize() +
- header.GetCollections().StringIdsSize() * dex_ir::StringId::ItemSize() +
- header.GetCollections().TypeIdsSize() * dex_ir::TypeId::ItemSize() +
- header.GetCollections().ProtoIdsSize() * dex_ir::ProtoId::ItemSize() +
- header.GetCollections().FieldIdsSize() * dex_ir::FieldId::ItemSize() +
- header.GetCollections().MethodIdsSize() * dex_ir::MethodId::ItemSize() +
- header.GetCollections().ClassDefsSize() * dex_ir::ClassDef::ItemSize();
-}
-
-static bool Align(File* file, uint32_t& offset) {
- uint8_t zero_buffer[] = { 0, 0, 0 };
- uint32_t zeroes = (-offset) & 3;
- if (zeroes > 0) {
- if (!file->PwriteFully(zero_buffer, zeroes, offset)) {
- return false;
- }
- offset += zeroes;
- }
- return true;
-}
-
-static bool WriteStrings(File* dex_file, dex_ir::Header& header,
- uint32_t& index_offset, uint32_t& data_offset) {
- uint32_t index = 0;
- uint32_t index_buffer[1];
- uint32_t string_length;
- uint32_t length_length;
- uint8_t length_buffer[8];
- for (std::unique_ptr<dex_ir::StringId>& string_id : header.GetCollections().StringIds()) {
- string_id->SetOffset(index);
- index_buffer[0] = data_offset;
- string_length = strlen(string_id->Data());
- length_length = UnsignedLeb128Size(string_length);
- EncodeUnsignedLeb128(length_buffer, string_length);
-
- if (!dex_file->PwriteFully(index_buffer, 4, index_offset) ||
- !dex_file->PwriteFully(length_buffer, length_length, data_offset) ||
- !dex_file->PwriteFully(string_id->Data(), string_length, data_offset + length_length)) {
- return false;
- }
-
- index++;
- index_offset += 4;
- data_offset += string_length + length_length;
- }
- return true;
-}
-
-static bool WriteTypes(File* dex_file, dex_ir::Header& header, uint32_t& index_offset) {
- uint32_t index = 0;
- uint32_t index_buffer[1];
- for (std::unique_ptr<dex_ir::TypeId>& type_id : header.GetCollections().TypeIds()) {
- type_id->SetIndex(index);
- index_buffer[0] = type_id->GetStringId()->GetOffset();
-
- if (!dex_file->PwriteFully(index_buffer, 4, index_offset)) {
- return false;
- }
-
- index++;
- index_offset += 4;
- }
- return true;
-}
-
-static bool WriteTypeLists(File* dex_file, dex_ir::Header& header, uint32_t& data_offset) {
- if (!Align(dex_file, data_offset)) {
- return false;
- }
-
- return true;
-}
-
-static void OutputDexFile(dex_ir::Header& header, const char* file_name) {
- LOG(INFO) << "FILE NAME: " << file_name;
- std::unique_ptr<File> dex_file(OS::CreateEmptyFileWriteOnly(file_name));
- if (dex_file == nullptr) {
- fprintf(stderr, "Can't open %s\n", file_name);
- return;
- }
-
- uint32_t index_offset = dex_ir::Header::ItemSize();
- uint32_t data_offset = GetDataSectionOffset(header);
- WriteStrings(dex_file.get(), header, index_offset, data_offset);
- WriteTypes(dex_file.get(), header, index_offset);
-}
-*/
-
-/*
* Dumps the requested sections of the file.
*/
static void ProcessDexFile(const char* file_name, const DexFile* dex_file, size_t dex_file_index) {
@@ -1634,13 +1546,13 @@
fprintf(out_file_, "</api>\n");
}
- /*
// Output dex file.
- if (options_.output_dex_files_) {
- std::string output_dex_filename = dex_file->GetLocation() + ".out";
- OutputDexFile(*header, output_dex_filename.c_str());
+ if (options_.output_dex_directory_ != nullptr) {
+ std::string output_location(options_.output_dex_directory_);
+ size_t last_slash = dex_file->GetLocation().rfind("/");
+ output_location.append(dex_file->GetLocation().substr(last_slash));
+ DexWriter::OutputDexFile(*header, output_location.c_str());
}
- */
}
/*
diff --git a/dexlayout/dexlayout.h b/dexlayout/dexlayout.h
index c4892d2..c01eb79 100644
--- a/dexlayout/dexlayout.h
+++ b/dexlayout/dexlayout.h
@@ -43,7 +43,6 @@
bool disassemble_;
bool exports_only_;
bool ignore_bad_checksum_;
- bool output_dex_files_;
bool show_annotations_;
bool show_cfg_;
bool show_file_headers_;
@@ -51,6 +50,7 @@
bool verbose_;
bool visualize_pattern_;
OutputFormat output_format_;
+ const char* output_dex_directory_;
const char* output_file_name_;
const char* profile_file_name_;
};
diff --git a/dexlayout/dexlayout_main.cc b/dexlayout/dexlayout_main.cc
index f385b09..728e389 100644
--- a/dexlayout/dexlayout_main.cc
+++ b/dexlayout/dexlayout_main.cc
@@ -43,7 +43,7 @@
static void Usage(void) {
fprintf(stderr, "Copyright (C) 2016 The Android Open Source Project\n\n");
fprintf(stderr, "%s: [-a] [-c] [-d] [-e] [-f] [-h] [-i] [-l layout] [-o outfile] [-p profile]"
- " [-s] [-w] dexfile...\n\n", kProgramName);
+ " [-s] [-w directory] dexfile...\n\n", kProgramName);
fprintf(stderr, " -a : display annotations\n");
fprintf(stderr, " -b : build dex_ir\n");
fprintf(stderr, " -c : verify checksum and exit\n");
@@ -57,7 +57,7 @@
fprintf(stderr, " -o : output file name (defaults to stdout)\n");
fprintf(stderr, " -p : profile file name (defaults to no profile)\n");
fprintf(stderr, " -s : visualize reference pattern\n");
- fprintf(stderr, " -w : output dex files\n");
+ fprintf(stderr, " -w : output dex directory \n");
}
/*
@@ -75,7 +75,7 @@
// Parse all arguments.
while (1) {
- const int ic = getopt(argc, argv, "abcdefghil:o:p:sw");
+ const int ic = getopt(argc, argv, "abcdefghil:o:p:sw:");
if (ic < 0) {
break; // done
}
@@ -127,8 +127,8 @@
options_.visualize_pattern_ = true;
options_.verbose_ = false;
break;
- case 'w': // output dex files
- options_.output_dex_files_ = true;
+ case 'w': // output dex files directory
+ options_.output_dex_directory_ = optarg;
break;
default:
want_usage = true;
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index 42b64c3..89544d7 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -31,43 +31,83 @@
protected:
virtual void SetUp() {
CommonRuntimeTest::SetUp();
- // TODO: Test with other dex files for improved coverage.
- // Dogfood our own lib core dex file.
- dex_file_ = GetLibCoreDexFileNames()[0];
}
- // Runs test with given arguments.
- bool Exec(std::string* error_msg) {
+ // Runs FullPlainOutput test.
+ bool FullPlainOutputExec(std::string* error_msg) {
// TODO: dexdump2 -> dexdump ?
ScratchFile dexdump_output;
std::string dexdump_filename = dexdump_output.GetFilename();
std::string dexdump = GetTestAndroidRoot() + "/bin/dexdump2";
EXPECT_TRUE(OS::FileExists(dexdump.c_str())) << dexdump << " should be a valid file path";
- std::vector<std::string> dexdump_exec_argv =
- { dexdump, "-d", "-f", "-h", "-l", "plain", "-o", dexdump_filename, dex_file_ };
ScratchFile dexlayout_output;
std::string dexlayout_filename = dexlayout_output.GetFilename();
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
- std::vector<std::string> dexlayout_exec_argv =
- { dexlayout, "-d", "-f", "-h", "-l", "plain", "-o", dexlayout_filename, dex_file_ };
- if (!::art::Exec(dexdump_exec_argv, error_msg)) {
- return false;
- }
- if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
- return false;
- }
- std::vector<std::string> diff_exec_argv =
- { "/usr/bin/diff", dexdump_filename, dexlayout_filename };
- if (!::art::Exec(diff_exec_argv, error_msg)) {
- return false;
+ for (const std::string &dex_file : GetLibCoreDexFileNames()) {
+ std::vector<std::string> dexdump_exec_argv =
+ { dexdump, "-d", "-f", "-h", "-l", "plain", "-o", dexdump_filename, dex_file };
+ std::vector<std::string> dexlayout_exec_argv =
+ { dexlayout, "-d", "-f", "-h", "-l", "plain", "-o", dexlayout_filename, dex_file };
+
+ if (!::art::Exec(dexdump_exec_argv, error_msg)) {
+ return false;
+ }
+ if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
+ return false;
+ }
+ std::vector<std::string> diff_exec_argv =
+ { "/usr/bin/diff", dexdump_filename, dexlayout_filename };
+ if (!::art::Exec(diff_exec_argv, error_msg)) {
+ return false;
+ }
}
return true;
}
- std::string dex_file_;
+ // Runs DexFileOutput test.
+ bool DexFileOutputExec(std::string* error_msg) {
+ ScratchFile tmp_file;
+ std::string tmp_name = tmp_file.GetFilename();
+ size_t tmp_last_slash = tmp_name.rfind("/");
+ std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
+ std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
+ EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
+
+ for (const std::string &dex_file : GetLibCoreDexFileNames()) {
+ std::vector<std::string> dexlayout_exec_argv =
+ { dexlayout, "-d", "-f", "-h", "-l", "plain", "-w", tmp_dir, "-o", tmp_name, dex_file };
+
+ if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
+ return false;
+ }
+
+ size_t dex_file_last_slash = dex_file.rfind("/");
+ std::string dex_file_name = dex_file.substr(dex_file_last_slash + 1);
+ std::vector<std::string> unzip_exec_argv =
+ { "/usr/bin/unzip", dex_file, "classes.dex", "-d", tmp_dir};
+ if (!::art::Exec(unzip_exec_argv, error_msg)) {
+ return false;
+ }
+ std::vector<std::string> diff_exec_argv =
+ { "/usr/bin/diff", tmp_dir + "classes.dex" , tmp_dir + dex_file_name };
+ if (!::art::Exec(diff_exec_argv, error_msg)) {
+ return false;
+ }
+ std::vector<std::string> rm_zip_exec_argv = { "/bin/rm", tmp_dir + "classes.dex" };
+ if (!::art::Exec(rm_zip_exec_argv, error_msg)) {
+ return false;
+ }
+ std::vector<std::string> rm_out_exec_argv = { "/bin/rm", tmp_dir + dex_file_name };
+ if (!::art::Exec(rm_out_exec_argv, error_msg)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
};
@@ -75,7 +115,14 @@
// Disable test on target.
TEST_DISABLED_FOR_TARGET();
std::string error_msg;
- ASSERT_TRUE(Exec(&error_msg)) << error_msg;
+ ASSERT_TRUE(FullPlainOutputExec(&error_msg)) << error_msg;
+}
+
+TEST_F(DexLayoutTest, DexFileOutput) {
+ // Disable test on target.
+ TEST_DISABLED_FOR_TARGET();
+ std::string error_msg;
+ ASSERT_TRUE(DexFileOutputExec(&error_msg)) << error_msg;
}
} // namespace art