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/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);
 };