Separate DexIr building from constructors.

Move all the construction from DexFile out of the constructors of the
basic IR.

Bug: 29921113
Change-Id: I3f79c104ce7183ddde73f143c047061416009a54
Test: test-art-host-gtest
diff --git a/dexlayout/Android.mk b/dexlayout/Android.mk
index 3095866..de02580 100755
--- a/dexlayout/Android.mk
+++ b/dexlayout/Android.mk
@@ -16,7 +16,7 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-dexlayout_src_files := dexlayout_main.cc dexlayout.cc dex_ir.cc
+dexlayout_src_files := dexlayout_main.cc dexlayout.cc dex_ir_builder.cc
 dexlayout_c_includes := art/runtime
 dexlayout_libraries := libart
 
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
deleted file mode 100644
index 0ed040e..0000000
--- a/dexlayout/dex_ir.cc
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * 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.
- *
- * Implementation file of the dex file intermediate representation.
- *
- * Utilities for reading dex files into an internal representation,
- * manipulating them, and writing them out.
- */
-
-#include "dex_ir.h"
-
-#include <map>
-#include <vector>
-
-#include "dex_file.h"
-#include "dex_file-inl.h"
-#include "utils.h"
-
-namespace art {
-namespace dex_ir {
-
-namespace {
-static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
-  uint64_t value = 0;
-  for (uint32_t i = 0; i <= length; i++) {
-    value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
-  }
-  if (sign_extend) {
-    int shift = (7 - length) * 8;
-    return (static_cast<int64_t>(value) << shift) >> shift;
-  }
-  return value;
-}
-
-static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) {
-  DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
-  std::vector<std::unique_ptr<PositionInfo>>& positions = debug_info->GetPositionInfo();
-  positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_)));
-  return false;
-}
-
-static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) {
-  DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
-  std::vector<std::unique_ptr<LocalInfo>>& locals = debug_info->GetLocalInfo();
-  const char* name = entry.name_ != nullptr ? entry.name_ : "(null)";
-  const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
-  locals.push_back(std::unique_ptr<LocalInfo>(
-      new LocalInfo(name, entry.descriptor_, signature, entry.start_address_,
-                    entry.end_address_, entry.reg_)));
-}
-}  // namespace
-
-Header::Header(const DexFile& dex_file) : dex_file_(dex_file) {
-  const DexFile::Header& disk_header = dex_file.GetHeader();
-  memcpy(magic_, disk_header.magic_, sizeof(magic_));
-  checksum_ = disk_header.checksum_;
-  // TODO(sehr): clearly the signature will need to be recomputed before dumping.
-  memcpy(signature_, disk_header.signature_, sizeof(signature_));
-  endian_tag_ = disk_header.endian_tag_;
-  file_size_ = disk_header.file_size_;
-  header_size_ = disk_header.header_size_;
-  link_size_ = disk_header.link_size_;
-  link_offset_ = disk_header.link_off_;
-  data_size_ = disk_header.data_size_;
-  data_offset_ = disk_header.data_off_;
-  // Walk the rest of the header fields.
-  string_ids_.SetOffset(disk_header.string_ids_off_);
-  for (uint32_t i = 0; i < dex_file_.NumStringIds(); ++i) {
-    string_ids_.AddWithPosition(i, new StringId(dex_file_.GetStringId(i), *this));
-  }
-  type_ids_.SetOffset(disk_header.type_ids_off_);
-  for (uint32_t i = 0; i < dex_file_.NumTypeIds(); ++i) {
-    type_ids_.AddWithPosition(i, new TypeId(dex_file_.GetTypeId(i), *this));
-  }
-  proto_ids_.SetOffset(disk_header.proto_ids_off_);
-  for (uint32_t i = 0; i < dex_file_.NumProtoIds(); ++i) {
-    proto_ids_.AddWithPosition(i, new ProtoId(dex_file_.GetProtoId(i), *this));
-  }
-  field_ids_.SetOffset(disk_header.field_ids_off_);
-  for (uint32_t i = 0; i < dex_file_.NumFieldIds(); ++i) {
-    field_ids_.AddWithPosition(i, new FieldId(dex_file_.GetFieldId(i), *this));
-  }
-  method_ids_.SetOffset(disk_header.method_ids_off_);
-  for (uint32_t i = 0; i < dex_file_.NumMethodIds(); ++i) {
-    method_ids_.AddWithPosition(i, new MethodId(dex_file_.GetMethodId(i), *this));
-  }
-  class_defs_.SetOffset(disk_header.class_defs_off_);
-  for (uint32_t i = 0; i < dex_file_.NumClassDefs(); ++i) {
-    class_defs_.AddWithPosition(i, new ClassDef(dex_file_.GetClassDef(i), *this));
-  }
-}
-
-ArrayItem::ArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length) {
-  Read(header, data, type, length);
-}
-
-ArrayItem::ArrayItem(Header& header, const uint8_t** data) {
-  const uint8_t encoded_value = *(*data)++;
-  Read(header, data, encoded_value & 0x1f, encoded_value >> 5);
-}
-
-void ArrayItem::Read(Header& header, const uint8_t** data, uint8_t type, uint8_t length) {
-  type_ = type;
-  switch (type_) {
-    case DexFile::kDexAnnotationByte:
-      item_.byte_val_ = static_cast<int8_t>(ReadVarWidth(data, length, false));
-      break;
-    case DexFile::kDexAnnotationShort:
-      item_.short_val_ = static_cast<int16_t>(ReadVarWidth(data, length, true));
-      break;
-    case DexFile::kDexAnnotationChar:
-      item_.char_val_ = static_cast<uint16_t>(ReadVarWidth(data, length, false));
-      break;
-    case DexFile::kDexAnnotationInt:
-      item_.int_val_ = static_cast<int32_t>(ReadVarWidth(data, length, true));
-      break;
-    case DexFile::kDexAnnotationLong:
-      item_.long_val_ = static_cast<int64_t>(ReadVarWidth(data, length, true));
-      break;
-    case DexFile::kDexAnnotationFloat: {
-      // Fill on right.
-      union {
-        float f;
-        uint32_t data;
-      } conv;
-      conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
-      item_.float_val_ = conv.f;
-      break;
-    }
-    case DexFile::kDexAnnotationDouble: {
-      // Fill on right.
-      union {
-        double d;
-        uint64_t data;
-      } conv;
-      conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
-      item_.double_val_ = conv.d;
-      break;
-    }
-    case DexFile::kDexAnnotationString: {
-      const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
-      item_.string_val_ = header.StringIds()[string_index].get();
-      break;
-    }
-    case DexFile::kDexAnnotationType: {
-      const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
-      item_.string_val_ = header.TypeIds()[string_index]->GetStringId();
-      break;
-    }
-    case DexFile::kDexAnnotationField:
-    case DexFile::kDexAnnotationEnum: {
-      const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
-      item_.field_val_ = header.FieldIds()[field_index].get();
-      break;
-    }
-    case DexFile::kDexAnnotationMethod: {
-      const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
-      item_.method_val_ = header.MethodIds()[method_index].get();
-      break;
-    }
-    case DexFile::kDexAnnotationArray: {
-      item_.annotation_array_val_ = new std::vector<std::unique_ptr<ArrayItem>>();
-      // Decode all elements.
-      const uint32_t size = DecodeUnsignedLeb128(data);
-      for (uint32_t i = 0; i < size; i++) {
-        item_.annotation_array_val_->push_back(
-            std::unique_ptr<ArrayItem>(new ArrayItem(header, data)));
-      }
-      break;
-    }
-    case DexFile::kDexAnnotationAnnotation: {
-      const uint32_t type_idx = DecodeUnsignedLeb128(data);
-      item_.annotation_annotation_val_.string_ = header.TypeIds()[type_idx]->GetStringId();
-      item_.annotation_annotation_val_.array_ = new std::vector<std::unique_ptr<NameValuePair>>();
-      // Decode all name=value pairs.
-      const uint32_t size = DecodeUnsignedLeb128(data);
-      for (uint32_t i = 0; i < size; i++) {
-        const uint32_t name_index = DecodeUnsignedLeb128(data);
-        item_.annotation_annotation_val_.array_->push_back(std::unique_ptr<NameValuePair>(
-            new NameValuePair(header.StringIds()[name_index].get(), new ArrayItem(header, data))));
-      }
-      break;
-    }
-    case DexFile::kDexAnnotationNull:
-      break;
-    case DexFile::kDexAnnotationBoolean:
-      item_.bool_val_ = (length != 0);
-      break;
-    default:
-      break;
-  }
-}
-
-ClassDef::ClassDef(const DexFile::ClassDef& disk_class_def, Header& header) {
-  class_type_ = header.TypeIds()[disk_class_def.class_idx_].get();
-  access_flags_ = disk_class_def.access_flags_;
-  superclass_ = header.GetTypeIdOrNullPtr(disk_class_def.superclass_idx_);
-
-  const DexFile::TypeList* type_list = header.GetDexFile().GetInterfacesList(disk_class_def);
-  interfaces_offset_ = disk_class_def.interfaces_off_;
-  if (type_list != nullptr) {
-    for (uint32_t index = 0; index < type_list->Size(); ++index) {
-      interfaces_.push_back(header.TypeIds()[type_list->GetTypeItem(index).type_idx_].get());
-    }
-  }
-  source_file_ = header.GetStringIdOrNullPtr(disk_class_def.source_file_idx_);
-  // Annotations.
-  const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
-      header.GetDexFile().GetAnnotationsDirectory(disk_class_def);
-  if (disk_annotations_directory_item == nullptr) {
-    annotations_.reset(nullptr);
-  } else {
-    annotations_.reset(new AnnotationsDirectoryItem(disk_annotations_directory_item, header));
-    annotations_->SetOffset(disk_class_def.annotations_off_);
-  }
-  // Static field initializers.
-  static_values_ = nullptr;
-  const uint8_t* static_data = header.GetDexFile().GetEncodedStaticFieldValuesArray(disk_class_def);
-  if (static_data != nullptr) {
-    uint32_t static_value_count = static_data == nullptr ? 0 : DecodeUnsignedLeb128(&static_data);
-    if (static_value_count > 0) {
-      static_values_ = new std::vector<std::unique_ptr<ArrayItem>>();
-      for (uint32_t i = 0; i < static_value_count; ++i) {
-        static_values_->push_back(std::unique_ptr<ArrayItem>(new ArrayItem(header, &static_data)));
-      }
-    }
-  }
-  // Read the fields and methods defined by the class, resolving the circular reference from those
-  // to classes by setting class at the same time.
-  const uint8_t* encoded_data = header.GetDexFile().GetClassData(disk_class_def);
-  class_data_.SetOffset(disk_class_def.class_data_off_);
-  if (encoded_data != nullptr) {
-    ClassDataItemIterator cdii(header.GetDexFile(), encoded_data);
-    // Static fields.
-    for (uint32_t i = 0; cdii.HasNextStaticField(); i++, cdii.Next()) {
-      FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get();
-      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
-      class_data_.StaticFields().push_back(
-          std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
-    }
-    // Instance fields.
-    for (uint32_t i = 0; cdii.HasNextInstanceField(); i++, cdii.Next()) {
-      FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get();
-      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
-      class_data_.InstanceFields().push_back(
-          std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
-    }
-    // Direct methods.
-    for (uint32_t i = 0; cdii.HasNextDirectMethod(); i++, cdii.Next()) {
-      class_data_.DirectMethods().push_back(
-          std::unique_ptr<MethodItem>(GenerateMethodItem(header, cdii)));
-    }
-    // Virtual methods.
-    for (uint32_t i = 0; cdii.HasNextVirtualMethod(); i++, cdii.Next()) {
-      class_data_.VirtualMethods().push_back(
-          std::unique_ptr<MethodItem>(GenerateMethodItem(header, cdii)));
-    }
-  }
-}
-
-MethodItem* ClassDef::GenerateMethodItem(Header& header, ClassDataItemIterator& cdii) {
-  MethodId* method_item = header.MethodIds()[cdii.GetMemberIndex()].get();
-  uint32_t access_flags = cdii.GetRawMemberAccessFlags();
-  const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
-  CodeItem* code_item = nullptr;
-  DebugInfoItem* debug_info = nullptr;
-  if (disk_code_item != nullptr) {
-    code_item = new CodeItem(*disk_code_item, header);
-    code_item->SetOffset(cdii.GetMethodCodeItemOffset());
-    debug_info = code_item->DebugInfo();
-  }
-  if (debug_info != nullptr) {
-    bool is_static = (access_flags & kAccStatic) != 0;
-    header.GetDexFile().DecodeDebugLocalInfo(
-        disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info);
-    header.GetDexFile().DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info);
-  }
-  return new MethodItem(access_flags, method_item, code_item);
-}
-
-CodeItem::CodeItem(const DexFile::CodeItem& disk_code_item, Header& header) {
-  registers_size_ = disk_code_item.registers_size_;
-  ins_size_ = disk_code_item.ins_size_;
-  outs_size_ = disk_code_item.outs_size_;
-  tries_size_ = disk_code_item.tries_size_;
-
-  const uint8_t* debug_info_stream = header.GetDexFile().GetDebugInfoStream(&disk_code_item);
-  if (debug_info_stream != nullptr) {
-    debug_info_.reset(new DebugInfoItem());
-  } else {
-    debug_info_.reset(nullptr);
-  }
-
-  insns_size_ = disk_code_item.insns_size_in_code_units_;
-  insns_.reset(new uint16_t[insns_size_]);
-  memcpy(insns_.get(), disk_code_item.insns_, insns_size_ * sizeof(uint16_t));
-
-  if (tries_size_ > 0) {
-    tries_ = new std::vector<std::unique_ptr<const TryItem>>();
-    for (uint32_t i = 0; i < tries_size_; ++i) {
-      const DexFile::TryItem* disk_try_item = header.GetDexFile().GetTryItems(disk_code_item, i);
-      tries_->push_back(std::unique_ptr<const TryItem>(
-          new TryItem(*disk_try_item, disk_code_item, header)));
-    }
-  } else {
-    tries_ = nullptr;
-  }
-}
-
-AnnotationSetItem::AnnotationSetItem(const DexFile::AnnotationSetItem& disk_annotations_item,
-                                     Header& header) {
-  if (disk_annotations_item.size_ == 0) {
-    return;
-  }
-  for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) {
-    const DexFile::AnnotationItem* annotation =
-        header.GetDexFile().GetAnnotationItem(&disk_annotations_item, i);
-    if (annotation == nullptr) {
-      continue;
-    }
-    uint8_t visibility = annotation->visibility_;
-    const uint8_t* annotation_data = annotation->annotation_;
-    ArrayItem* array_item =
-        new ArrayItem(header, &annotation_data, DexFile::kDexAnnotationAnnotation, 0);
-    items_.push_back(std::unique_ptr<AnnotationItem>(new AnnotationItem(visibility, array_item)));
-  }
-}
-
-AnnotationsDirectoryItem::AnnotationsDirectoryItem(
-    const DexFile::AnnotationsDirectoryItem* disk_annotations_item, Header& header) {
-  const DexFile::AnnotationSetItem* class_set_item =
-      header.GetDexFile().GetClassAnnotationSet(disk_annotations_item);
-  if (class_set_item == nullptr) {
-    class_annotation_.reset(nullptr);
-  } else {
-    class_annotation_.reset(new AnnotationSetItem(*class_set_item, header));
-  }
-  const DexFile::FieldAnnotationsItem* fields =
-      header.GetDexFile().GetFieldAnnotations(disk_annotations_item);
-  if (fields != nullptr) {
-    for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
-      FieldId* field_id = header.FieldIds()[fields[i].field_idx_].get();
-      const DexFile::AnnotationSetItem* field_set_item =
-          header.GetDexFile().GetFieldAnnotationSetItem(fields[i]);
-      dex_ir::AnnotationSetItem* annotation_set_item =
-          new AnnotationSetItem(*field_set_item, header);
-      field_annotations_.push_back(std::unique_ptr<FieldAnnotation>(
-          new FieldAnnotation(field_id, annotation_set_item)));
-    }
-  }
-  const DexFile::MethodAnnotationsItem* methods =
-      header.GetDexFile().GetMethodAnnotations(disk_annotations_item);
-  if (methods != nullptr) {
-    for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
-      MethodId* method_id = header.MethodIds()[methods[i].method_idx_].get();
-      const DexFile::AnnotationSetItem* method_set_item =
-          header.GetDexFile().GetMethodAnnotationSetItem(methods[i]);
-      dex_ir::AnnotationSetItem* annotation_set_item =
-          new AnnotationSetItem(*method_set_item, header);
-      method_annotations_.push_back(std::unique_ptr<MethodAnnotation>(
-          new MethodAnnotation(method_id, annotation_set_item)));
-    }
-  }
-  const DexFile::ParameterAnnotationsItem* parameters =
-      header.GetDexFile().GetParameterAnnotations(disk_annotations_item);
-  if (parameters != nullptr) {
-    for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
-      MethodId* method_id = header.MethodIds()[parameters[i].method_idx_].get();
-      const DexFile::AnnotationSetRefList* list =
-          header.GetDexFile().GetParameterAnnotationSetRefList(&parameters[i]);
-      parameter_annotations_.push_back(std::unique_ptr<ParameterAnnotation>(
-          new ParameterAnnotation(method_id, list, header)));
-    }
-  }
-}
-
-}  // namespace dex_ir
-}  // namespace art
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index fcd3ab0..514d6fd 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -19,12 +19,10 @@
 #ifndef ART_DEXLAYOUT_DEX_IR_H_
 #define ART_DEXLAYOUT_DEX_IR_H_
 
-#include <iostream>
-#include <map>
 #include <vector>
 #include <stdint.h>
 
-#include "dex_file.h"
+#include "dex_file-inl.h"
 
 namespace art {
 namespace dex_ir {
@@ -106,19 +104,39 @@
 class Item {
  public:
   virtual ~Item() { }
+
   uint32_t GetOffset() const { return offset_; }
   void SetOffset(uint32_t offset) { offset_ = offset; }
+
  protected:
   uint32_t offset_ = 0;
 };
 
 class Header : public Item {
  public:
-  explicit Header(const DexFile& dex_file);
+  Header(const uint8_t* magic,
+         uint32_t checksum,
+         const uint8_t* signature,
+         uint32_t endian_tag,
+         uint32_t file_size,
+         uint32_t header_size,
+         uint32_t link_size,
+         uint32_t link_offset,
+         uint32_t data_size,
+         uint32_t data_offset)
+      : checksum_(checksum),
+        endian_tag_(endian_tag),
+        file_size_(file_size),
+        header_size_(header_size),
+        link_size_(link_size),
+        link_offset_(link_offset),
+        data_size_(data_size),
+        data_offset_(data_offset) {
+    memcpy(magic_, magic, sizeof(magic_));
+    memcpy(signature_, signature, sizeof(signature_));
+  }
   ~Header() OVERRIDE { }
 
-  const DexFile& GetDexFile() const { return dex_file_; }
-
   const uint8_t* Magic() const { return magic_; }
   uint32_t Checksum() const { return checksum_; }
   const uint8_t* Signature() const { return signature_; }
@@ -178,7 +196,6 @@
   void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
 
  private:
-  const DexFile& dex_file_;
   uint8_t magic_[8];
   uint32_t checksum_;
   uint8_t signature_[DexFile::kSha1DigestSize];
@@ -201,9 +218,7 @@
 
 class StringId : public Item {
  public:
-  StringId(const DexFile::StringId& disk_string_id, Header& header) :
-    data_(strdup(header.GetDexFile().GetStringData(disk_string_id))) {
-  }
+  explicit StringId(const char* data) : data_(strdup(data)) { }
   ~StringId() OVERRIDE { }
 
   const char* Data() const { return data_.get(); }
@@ -217,9 +232,7 @@
 
 class TypeId : public Item {
  public:
-  TypeId(const DexFile::TypeId& disk_type_id, Header& header) :
-    string_id_(header.StringIds()[disk_type_id.descriptor_idx_].get()) {
-  }
+  explicit TypeId(StringId* string_id) : string_id_(string_id) { }
   ~TypeId() OVERRIDE { }
 
   StringId* GetStringId() const { return string_id_; }
@@ -231,39 +244,31 @@
   DISALLOW_COPY_AND_ASSIGN(TypeId);
 };
 
+using TypeIdVector = std::vector<const TypeId*>;
+
 class ProtoId : public Item {
  public:
-  ProtoId(const DexFile::ProtoId& disk_proto_id, Header& header) {
-    shorty_ = header.StringIds()[disk_proto_id.shorty_idx_].get();
-    return_type_ = header.TypeIds()[disk_proto_id.return_type_idx_].get();
-    DexFileParameterIterator dfpi(header.GetDexFile(), disk_proto_id);
-    while (dfpi.HasNext()) {
-      parameters_.push_back(header.TypeIds()[dfpi.GetTypeIdx()].get());
-      dfpi.Next();
-    }
-  }
+  ProtoId(const StringId* shorty, const TypeId* return_type, TypeIdVector* parameters)
+      : shorty_(shorty), return_type_(return_type), parameters_(parameters) { }
   ~ProtoId() OVERRIDE { }
 
   const StringId* Shorty() const { return shorty_; }
   const TypeId* ReturnType() const { return return_type_; }
-  const std::vector<const TypeId*>& Parameters() const { return parameters_; }
+  const std::vector<const TypeId*>& Parameters() const { return *parameters_; }
 
   void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
 
  private:
   const StringId* shorty_;
   const TypeId* return_type_;
-  std::vector<const TypeId*> parameters_;
+  std::unique_ptr<TypeIdVector> parameters_;
   DISALLOW_COPY_AND_ASSIGN(ProtoId);
 };
 
 class FieldId : public Item {
  public:
-  FieldId(const DexFile::FieldId& disk_field_id, Header& header) {
-    class_ = header.TypeIds()[disk_field_id.class_idx_].get();
-    type_ = header.TypeIds()[disk_field_id.type_idx_].get();
-    name_ = header.StringIds()[disk_field_id.name_idx_].get();
-  }
+  FieldId(const TypeId* klass, const TypeId* type, const StringId* name)
+      : class_(klass), type_(type), name_(name) { }
   ~FieldId() OVERRIDE { }
 
   const TypeId* Class() const { return class_; }
@@ -281,11 +286,8 @@
 
 class MethodId : public Item {
  public:
-  MethodId(const DexFile::MethodId& disk_method_id, Header& header) {
-    class_ = header.TypeIds()[disk_method_id.class_idx_].get();
-    proto_ = header.ProtoIds()[disk_method_id.proto_idx_].get();
-    name_ = header.StringIds()[disk_method_id.name_idx_].get();
-  }
+  MethodId(const TypeId* klass, const ProtoId* proto, const StringId* name)
+      : class_(klass), proto_(proto), name_(name) { }
   ~MethodId() OVERRIDE { }
 
   const TypeId* Class() const { return class_; }
@@ -303,8 +305,8 @@
 
 class FieldItem : public Item {
  public:
-  FieldItem(uint32_t access_flags, const FieldId* field_id) :
-    access_flags_(access_flags), field_id_(field_id) { }
+  FieldItem(uint32_t access_flags, const FieldId* field_id)
+      : access_flags_(access_flags), field_id_(field_id) { }
   ~FieldItem() OVERRIDE { }
 
   uint32_t GetAccessFlags() const { return access_flags_; }
@@ -318,10 +320,12 @@
   DISALLOW_COPY_AND_ASSIGN(FieldItem);
 };
 
+using FieldItemVector = std::vector<std::unique_ptr<FieldItem>>;
+
 class MethodItem : public Item {
  public:
-  MethodItem(uint32_t access_flags, const MethodId* method_id, const CodeItem* code) :
-    access_flags_(access_flags), method_id_(method_id), code_(code) { }
+  MethodItem(uint32_t access_flags, const MethodId* method_id, const CodeItem* code)
+      : access_flags_(access_flags), method_id_(method_id), code_(code) { }
   ~MethodItem() OVERRIDE { }
 
   uint32_t GetAccessFlags() const { return access_flags_; }
@@ -337,12 +341,14 @@
   DISALLOW_COPY_AND_ASSIGN(MethodItem);
 };
 
+using MethodItemVector = std::vector<std::unique_ptr<MethodItem>>;
+
 class ArrayItem : public Item {
  public:
   class NameValuePair {
    public:
-    NameValuePair(StringId* name, ArrayItem* value) :
-      name_(name), value_(value) { }
+    NameValuePair(StringId* name, ArrayItem* value)
+        : name_(name), value_(value) { }
 
     StringId* Name() const { return name_; }
     ArrayItem* Value() const { return value_.get(); }
@@ -353,8 +359,26 @@
     DISALLOW_COPY_AND_ASSIGN(NameValuePair);
   };
 
-  ArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length);
-  ArrayItem(Header& header, const uint8_t** data);
+  union PayloadUnion {
+    bool bool_val_;
+    int8_t byte_val_;
+    int16_t short_val_;
+    uint16_t char_val_;
+    int32_t int_val_;
+    int64_t long_val_;
+    float float_val_;
+    double double_val_;
+    StringId* string_val_;
+    FieldId* field_val_;
+    MethodId* method_val_;
+    std::vector<std::unique_ptr<ArrayItem>>* annotation_array_val_;
+    struct {
+      StringId* string_;
+      std::vector<std::unique_ptr<NameValuePair>>* array_;
+    } annotation_annotation_val_;
+  };
+
+  explicit ArrayItem(uint8_t type) : type_(type) { }
   ~ArrayItem() OVERRIDE { }
 
   int8_t Type() const { return type_; }
@@ -378,67 +402,79 @@
   std::vector<std::unique_ptr<NameValuePair>>* GetAnnotationAnnotationNameValuePairArray() const {
     return item_.annotation_annotation_val_.array_;
   }
+  // Used to construct the item union.  Ugly, but necessary.
+  PayloadUnion* GetPayloadUnion() { return &item_; }
 
   void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
 
  private:
-  void Read(Header& header, const uint8_t** data, uint8_t type, uint8_t length);
   uint8_t type_;
-  union {
-    bool bool_val_;
-    int8_t byte_val_;
-    int16_t short_val_;
-    uint16_t char_val_;
-    int32_t int_val_;
-    int64_t long_val_;
-    float float_val_;
-    double double_val_;
-    StringId* string_val_;
-    FieldId* field_val_;
-    MethodId* method_val_;
-    std::vector<std::unique_ptr<ArrayItem>>* annotation_array_val_;
-    struct {
-      StringId* string_;
-      std::vector<std::unique_ptr<NameValuePair>>* array_;
-    } annotation_annotation_val_;
-  } item_;
+  PayloadUnion item_;
   DISALLOW_COPY_AND_ASSIGN(ArrayItem);
 };
 
+using ArrayItemVector = std::vector<std::unique_ptr<ArrayItem>>;
+
 class ClassData : public Item {
  public:
-  ClassData() = default;
+  ClassData(FieldItemVector* static_fields,
+            FieldItemVector* instance_fields,
+            MethodItemVector* direct_methods,
+            MethodItemVector* virtual_methods)
+      : static_fields_(static_fields),
+        instance_fields_(instance_fields),
+        direct_methods_(direct_methods),
+        virtual_methods_(virtual_methods) { }
+
   ~ClassData() OVERRIDE = default;
-  std::vector<std::unique_ptr<FieldItem>>& StaticFields() { return static_fields_; }
-  std::vector<std::unique_ptr<FieldItem>>& InstanceFields() { return instance_fields_; }
-  std::vector<std::unique_ptr<MethodItem>>& DirectMethods() { return direct_methods_; }
-  std::vector<std::unique_ptr<MethodItem>>& VirtualMethods() { return virtual_methods_; }
+  FieldItemVector* StaticFields() { return static_fields_.get(); }
+  FieldItemVector* InstanceFields() { return instance_fields_.get(); }
+  MethodItemVector* DirectMethods() { return direct_methods_.get(); }
+  MethodItemVector* VirtualMethods() { return virtual_methods_.get(); }
 
   void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
 
  private:
-  std::vector<std::unique_ptr<FieldItem>> static_fields_;
-  std::vector<std::unique_ptr<FieldItem>> instance_fields_;
-  std::vector<std::unique_ptr<MethodItem>> direct_methods_;
-  std::vector<std::unique_ptr<MethodItem>> virtual_methods_;
+  std::unique_ptr<FieldItemVector> static_fields_;
+  std::unique_ptr<FieldItemVector> instance_fields_;
+  std::unique_ptr<MethodItemVector> direct_methods_;
+  std::unique_ptr<MethodItemVector> virtual_methods_;
   DISALLOW_COPY_AND_ASSIGN(ClassData);
 };
 
 class ClassDef : public Item {
  public:
-  ClassDef(const DexFile::ClassDef& disk_class_def, Header& header);
+  ClassDef(const TypeId* class_type,
+           uint32_t access_flags,
+           const TypeId* superclass,
+           TypeIdVector* interfaces,
+           uint32_t interfaces_offset,
+           const StringId* source_file,
+           AnnotationsDirectoryItem* annotations,
+           ArrayItemVector* static_values,
+           ClassData* class_data)
+      : class_type_(class_type),
+        access_flags_(access_flags),
+        superclass_(superclass),
+        interfaces_(interfaces),
+        interfaces_offset_(interfaces_offset),
+        source_file_(source_file),
+        annotations_(annotations),
+        static_values_(static_values),
+        class_data_(class_data) { }
+
   ~ClassDef() OVERRIDE { }
 
   const TypeId* ClassType() const { return class_type_; }
   uint32_t GetAccessFlags() const { return access_flags_; }
   const TypeId* Superclass() const { return superclass_; }
-  std::vector<TypeId*>* Interfaces() { return &interfaces_; }
+  TypeIdVector* Interfaces() { return interfaces_.get(); }
   uint32_t InterfacesOffset() const { return interfaces_offset_; }
   void SetInterfacesOffset(uint32_t new_offset) { interfaces_offset_ = new_offset; }
   const StringId* SourceFile() const { return source_file_; }
   AnnotationsDirectoryItem* Annotations() const { return annotations_.get(); }
-  std::vector<std::unique_ptr<ArrayItem>>* StaticValues() { return static_values_; }
-  ClassData* GetClassData() { return &class_data_; }
+  ArrayItemVector* StaticValues() { return static_values_.get(); }
+  ClassData* GetClassData() { return class_data_.get(); }
 
   MethodItem* GenerateMethodItem(Header& header, ClassDataItemIterator& cdii);
 
@@ -448,28 +484,78 @@
   const TypeId* class_type_;
   uint32_t access_flags_;
   const TypeId* superclass_;
-  std::vector<TypeId*> interfaces_;
+  std::unique_ptr<TypeIdVector> interfaces_;
   uint32_t interfaces_offset_;
   const StringId* source_file_;
   std::unique_ptr<AnnotationsDirectoryItem> annotations_;
-  std::vector<std::unique_ptr<ArrayItem>>* static_values_;
-  ClassData class_data_;
+  std::unique_ptr<ArrayItemVector> static_values_;
+  std::unique_ptr<ClassData> class_data_;
   DISALLOW_COPY_AND_ASSIGN(ClassDef);
 };
 
+class CatchHandler {
+ public:
+  CatchHandler(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_; }
+
+ private:
+  const TypeId* type_id_;
+  uint32_t address_;
+  DISALLOW_COPY_AND_ASSIGN(CatchHandler);
+};
+
+using CatchHandlerVector = std::vector<std::unique_ptr<const CatchHandler>>;
+
+class TryItem : public Item {
+ public:
+  TryItem(uint32_t start_addr, uint16_t insn_count, CatchHandlerVector* 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(); }
+
+  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
+
+ private:
+  uint32_t start_addr_;
+  uint16_t insn_count_;
+  std::unique_ptr<CatchHandlerVector> handlers_;
+  DISALLOW_COPY_AND_ASSIGN(TryItem);
+};
+
+using TryItemVector = std::vector<std::unique_ptr<const TryItem>>;
+
 class CodeItem : public Item {
  public:
-  CodeItem(const DexFile::CodeItem& disk_code_item, Header& header);
+  CodeItem(uint16_t registers_size,
+           uint16_t ins_size,
+           uint16_t outs_size,
+           DebugInfoItem* debug_info,
+           uint32_t insns_size,
+           uint16_t* insns,
+           TryItemVector* tries)
+      : registers_size_(registers_size),
+        ins_size_(ins_size),
+        outs_size_(outs_size),
+        debug_info_(debug_info),
+        insns_size_(insns_size),
+        insns_(insns),
+        tries_(tries) { }
+
   ~CodeItem() OVERRIDE { }
 
   uint16_t RegistersSize() const { return registers_size_; }
   uint16_t InsSize() const { return ins_size_; }
   uint16_t OutsSize() const { return outs_size_; }
-  uint16_t TriesSize() const { return tries_size_; }
+  uint16_t TriesSize() const { return tries_ == nullptr ? 0 : tries_->size(); }
   DebugInfoItem* DebugInfo() const { return debug_info_.get(); }
   uint32_t InsnsSize() const { return insns_size_; }
   uint16_t* Insns() const { return insns_.get(); }
-  std::vector<std::unique_ptr<const TryItem>>* Tries() const { return tries_; }
+  TryItemVector* Tries() const { return tries_.get(); }
 
   void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
 
@@ -477,56 +563,13 @@
   uint16_t registers_size_;
   uint16_t ins_size_;
   uint16_t outs_size_;
-  uint16_t tries_size_;
   std::unique_ptr<DebugInfoItem> debug_info_;
   uint32_t insns_size_;
   std::unique_ptr<uint16_t[]> insns_;
-  std::vector<std::unique_ptr<const TryItem>>* tries_;
+  std::unique_ptr<TryItemVector> tries_;
   DISALLOW_COPY_AND_ASSIGN(CodeItem);
 };
 
-class TryItem : public Item {
- public:
-  class CatchHandler {
-   public:
-    CatchHandler(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_; }
-
-   private:
-    const TypeId* type_id_;
-    uint32_t address_;
-    DISALLOW_COPY_AND_ASSIGN(CatchHandler);
-  };
-
-  TryItem(const DexFile::TryItem& disk_try_item,
-          const DexFile::CodeItem& disk_code_item,
-          Header& header) {
-    start_addr_ = disk_try_item.start_addr_;
-    insn_count_ = disk_try_item.insn_count_;
-    for (CatchHandlerIterator it(disk_code_item, disk_try_item); it.HasNext(); it.Next()) {
-      const uint16_t type_index = it.GetHandlerTypeIndex();
-      const TypeId* type_id = header.GetTypeIdOrNullPtr(type_index);
-      handlers_.push_back(std::unique_ptr<const CatchHandler>(
-          new CatchHandler(type_id, it.GetHandlerAddress())));
-    }
-  }
-  ~TryItem() OVERRIDE { }
-
-  uint32_t StartAddr() const { return start_addr_; }
-  uint16_t InsnCount() const { return insn_count_; }
-  const std::vector<std::unique_ptr<const CatchHandler>>& GetHandlers() const { return handlers_; }
-
-  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
-
- private:
-  uint32_t start_addr_;
-  uint16_t insn_count_;
-  std::vector<std::unique_ptr<const CatchHandler>> handlers_;
-  DISALLOW_COPY_AND_ASSIGN(TryItem);
-};
-
 
 struct PositionInfo {
   PositionInfo(uint32_t address, uint32_t line) : address_(address), line_(line) { }
@@ -535,11 +578,21 @@
   uint32_t line_;
 };
 
+using PositionInfoVector = std::vector<std::unique_ptr<PositionInfo>>;
+
 struct LocalInfo {
-  LocalInfo(const char* name, const char* descriptor, const char* signature, uint32_t start_address,
-            uint32_t end_address, uint16_t reg) :
-    name_(name), descriptor_(descriptor), signature_(signature), start_address_(start_address),
-    end_address_(end_address), reg_(reg) { }
+  LocalInfo(const char* name,
+            const char* descriptor,
+            const char* signature,
+            uint32_t start_address,
+            uint32_t end_address,
+            uint16_t reg)
+      : name_(name),
+        descriptor_(descriptor),
+        signature_(signature),
+        start_address_(start_address),
+        end_address_(end_address),
+        reg_(reg) { }
 
   std::string name_;
   std::string descriptor_;
@@ -549,124 +602,123 @@
   uint16_t reg_;
 };
 
+using LocalInfoVector = std::vector<std::unique_ptr<LocalInfo>>;
+
 class DebugInfoItem : public Item {
  public:
   DebugInfoItem() = default;
 
-  std::vector<std::unique_ptr<PositionInfo>>& GetPositionInfo() { return positions_; }
-  std::vector<std::unique_ptr<LocalInfo>>& GetLocalInfo() { return locals_; }
+  PositionInfoVector& GetPositionInfo() { return positions_; }
+  LocalInfoVector& GetLocalInfo() { return locals_; }
 
  private:
-  std::vector<std::unique_ptr<PositionInfo>> positions_;
-  std::vector<std::unique_ptr<LocalInfo>> locals_;
+  PositionInfoVector positions_;
+  LocalInfoVector locals_;
   DISALLOW_COPY_AND_ASSIGN(DebugInfoItem);
 };
 
+class AnnotationItem {
+ public:
+  AnnotationItem(uint8_t visibility, ArrayItem* item) : visibility_(visibility), item_(item) { }
+
+  uint8_t GetVisibility() const { return visibility_; }
+  ArrayItem* GetItem() const { return item_.get(); }
+
+ private:
+  uint8_t visibility_;
+  std::unique_ptr<ArrayItem> item_;
+  DISALLOW_COPY_AND_ASSIGN(AnnotationItem);
+};
+
+using AnnotationItemVector = std::vector<std::unique_ptr<AnnotationItem>>;
+
 class AnnotationSetItem : public Item {
  public:
-  class AnnotationItem {
-   public:
-    AnnotationItem(uint8_t visibility, ArrayItem* item) :
-      visibility_(visibility), item_(item) { }
-
-    uint8_t GetVisibility() const { return visibility_; }
-    ArrayItem* GetItem() const { return item_.get(); }
-
-   private:
-    uint8_t visibility_;
-    std::unique_ptr<ArrayItem> item_;
-    DISALLOW_COPY_AND_ASSIGN(AnnotationItem);
-  };
-
-  AnnotationSetItem(const DexFile::AnnotationSetItem& disk_annotations_item, Header& header);
+  explicit AnnotationSetItem(AnnotationItemVector* items) : items_(items) { }
   ~AnnotationSetItem() OVERRIDE { }
 
-  std::vector<std::unique_ptr<AnnotationItem>>& GetItems() { return items_; }
+  AnnotationItemVector* GetItems() { return items_.get(); }
 
   void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
 
  private:
-  std::vector<std::unique_ptr<AnnotationItem>> items_;
+  std::unique_ptr<AnnotationItemVector> items_;
   DISALLOW_COPY_AND_ASSIGN(AnnotationSetItem);
 };
 
+using AnnotationSetItemVector = std::vector<std::unique_ptr<AnnotationSetItem>>;
+
+class FieldAnnotation {
+ public:
+  FieldAnnotation(FieldId* field_id, AnnotationSetItem* annotation_set_item)
+      : field_id_(field_id), annotation_set_item_(annotation_set_item) { }
+
+  FieldId* GetFieldId() const { return field_id_; }
+  AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
+
+ private:
+  FieldId* field_id_;
+  std::unique_ptr<AnnotationSetItem> annotation_set_item_;
+  DISALLOW_COPY_AND_ASSIGN(FieldAnnotation);
+};
+
+using FieldAnnotationVector = std::vector<std::unique_ptr<FieldAnnotation>>;
+
+class MethodAnnotation {
+ public:
+  MethodAnnotation(MethodId* method_id, AnnotationSetItem* annotation_set_item)
+      : method_id_(method_id), annotation_set_item_(annotation_set_item) { }
+
+  MethodId* GetMethodId() const { return method_id_; }
+  AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
+
+ private:
+  MethodId* method_id_;
+  std::unique_ptr<AnnotationSetItem> annotation_set_item_;
+  DISALLOW_COPY_AND_ASSIGN(MethodAnnotation);
+};
+
+using MethodAnnotationVector = std::vector<std::unique_ptr<MethodAnnotation>>;
+
+class ParameterAnnotation {
+ public:
+  ParameterAnnotation(MethodId* method_id, AnnotationSetItemVector* annotations)
+      : method_id_(method_id), annotations_(annotations) { }
+
+  MethodId* GetMethodId() const { return method_id_; }
+  AnnotationSetItemVector* GetAnnotations() { return annotations_.get(); }
+
+ private:
+  MethodId* method_id_;
+  std::unique_ptr<AnnotationSetItemVector> annotations_;
+  DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation);
+};
+
+using ParameterAnnotationVector = std::vector<std::unique_ptr<ParameterAnnotation>>;
+
 class AnnotationsDirectoryItem : public Item {
  public:
-  class FieldAnnotation {
-   public:
-    FieldAnnotation(FieldId* field_id, AnnotationSetItem* annotation_set_item) :
-      field_id_(field_id), annotation_set_item_(annotation_set_item) { }
-
-    FieldId* GetFieldId() const { return field_id_; }
-    AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
-
-   private:
-    FieldId* field_id_;
-    std::unique_ptr<AnnotationSetItem> annotation_set_item_;
-    DISALLOW_COPY_AND_ASSIGN(FieldAnnotation);
-  };
-
-  class MethodAnnotation {
-   public:
-    MethodAnnotation(MethodId* method_id, AnnotationSetItem* annotation_set_item) :
-      method_id_(method_id), annotation_set_item_(annotation_set_item) { }
-
-    MethodId* GetMethodId() const { return method_id_; }
-    AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
-
-   private:
-    MethodId* method_id_;
-    std::unique_ptr<AnnotationSetItem> annotation_set_item_;
-    DISALLOW_COPY_AND_ASSIGN(MethodAnnotation);
-  };
-
-  class ParameterAnnotation {
-   public:
-    ParameterAnnotation(MethodId* method_id,
-                        const DexFile::AnnotationSetRefList* annotation_set_ref_list,
-                        Header& header) :
-      method_id_(method_id) {
-      for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
-        const DexFile::AnnotationSetItem* annotation_set_item =
-            header.GetDexFile().GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
-        annotations_.push_back(std::unique_ptr<AnnotationSetItem>(
-            new AnnotationSetItem(*annotation_set_item, header)));
-      }
-    }
-
-    MethodId* GetMethodId() const { return method_id_; }
-    std::vector<std::unique_ptr<AnnotationSetItem>>& GetAnnotations() { return annotations_; }
-
-   private:
-    MethodId* method_id_;
-    std::vector<std::unique_ptr<AnnotationSetItem>> annotations_;
-    DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation);
-  };
-
-  AnnotationsDirectoryItem(const DexFile::AnnotationsDirectoryItem* disk_annotations_item,
-                           Header& header);
+  AnnotationsDirectoryItem(AnnotationSetItem* class_annotation,
+                           FieldAnnotationVector* field_annotations,
+                           MethodAnnotationVector* method_annotations,
+                           ParameterAnnotationVector* parameter_annotations)
+      : class_annotation_(class_annotation),
+        field_annotations_(field_annotations),
+        method_annotations_(method_annotations),
+        parameter_annotations_(parameter_annotations) { }
 
   AnnotationSetItem* GetClassAnnotation() const { return class_annotation_.get(); }
-
-  std::vector<std::unique_ptr<FieldAnnotation>>& GetFieldAnnotations() {
-    return field_annotations_;
-  }
-
-  std::vector<std::unique_ptr<MethodAnnotation>>& GetMethodAnnotations() {
-    return method_annotations_;
-  }
-
-  std::vector<std::unique_ptr<ParameterAnnotation>>& GetParameterAnnotations() {
-    return parameter_annotations_;
-  }
+  FieldAnnotationVector* GetFieldAnnotations() { return field_annotations_.get(); }
+  MethodAnnotationVector* GetMethodAnnotations() { return method_annotations_.get(); }
+  ParameterAnnotationVector* GetParameterAnnotations() { return parameter_annotations_.get(); }
 
   void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
 
  private:
   std::unique_ptr<AnnotationSetItem> class_annotation_;
-  std::vector<std::unique_ptr<FieldAnnotation>> field_annotations_;
-  std::vector<std::unique_ptr<MethodAnnotation>> method_annotations_;
-  std::vector<std::unique_ptr<ParameterAnnotation>> parameter_annotations_;
+  std::unique_ptr<FieldAnnotationVector> field_annotations_;
+  std::unique_ptr<MethodAnnotationVector> method_annotations_;
+  std::unique_ptr<ParameterAnnotationVector> parameter_annotations_;
   DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem);
 };
 
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
new file mode 100644
index 0000000..38f35e7
--- /dev/null
+++ b/dexlayout/dex_ir_builder.cc
@@ -0,0 +1,507 @@
+/*
+ * 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 <vector>
+
+#include "dex_ir_builder.h"
+
+namespace art {
+namespace dex_ir {
+
+namespace {
+
+static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
+  uint64_t value = 0;
+  for (uint32_t i = 0; i <= length; i++) {
+    value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
+  }
+  if (sign_extend) {
+    int shift = (7 - length) * 8;
+    return (static_cast<int64_t>(value) << shift) >> shift;
+  }
+  return value;
+}
+
+// Prototype to break cyclic dependency.
+void ReadPayloadUnion(Header& header,
+                      const uint8_t** data,
+                      uint8_t type,
+                      uint8_t length,
+                      ArrayItem::PayloadUnion* item);
+
+ArrayItem* ReadArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length) {
+  ArrayItem* item = new ArrayItem(type);
+  ReadPayloadUnion(header, data, type, length, item->GetPayloadUnion());
+  return item;
+}
+
+ArrayItem* ReadArrayItem(Header& header, const uint8_t** data) {
+  const uint8_t encoded_value = *(*data)++;
+  const uint8_t type = encoded_value & 0x1f;
+  ArrayItem* item = new ArrayItem(type);
+  ReadPayloadUnion(header, data, type, encoded_value >> 5, item->GetPayloadUnion());
+  return item;
+}
+
+void ReadPayloadUnion(Header& header,
+                      const uint8_t** data,
+                      uint8_t type,
+                      uint8_t length,
+                      ArrayItem::PayloadUnion* item) {
+  switch (type) {
+    case DexFile::kDexAnnotationByte:
+      item->byte_val_ = static_cast<int8_t>(ReadVarWidth(data, length, false));
+      break;
+    case DexFile::kDexAnnotationShort:
+      item->short_val_ = static_cast<int16_t>(ReadVarWidth(data, length, true));
+      break;
+    case DexFile::kDexAnnotationChar:
+      item->char_val_ = static_cast<uint16_t>(ReadVarWidth(data, length, false));
+      break;
+    case DexFile::kDexAnnotationInt:
+      item->int_val_ = static_cast<int32_t>(ReadVarWidth(data, length, true));
+      break;
+    case DexFile::kDexAnnotationLong:
+      item->long_val_ = static_cast<int64_t>(ReadVarWidth(data, length, true));
+      break;
+    case DexFile::kDexAnnotationFloat: {
+      // Fill on right.
+      union {
+        float f;
+        uint32_t data;
+      } conv;
+      conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
+      item->float_val_ = conv.f;
+      break;
+    }
+    case DexFile::kDexAnnotationDouble: {
+      // Fill on right.
+      union {
+        double d;
+        uint64_t data;
+      } conv;
+      conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
+      item->double_val_ = conv.d;
+      break;
+    }
+    case DexFile::kDexAnnotationString: {
+      const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->string_val_ = header.StringIds()[string_index].get();
+      break;
+    }
+    case DexFile::kDexAnnotationType: {
+      const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->string_val_ = header.TypeIds()[string_index]->GetStringId();
+      break;
+    }
+    case DexFile::kDexAnnotationField:
+    case DexFile::kDexAnnotationEnum: {
+      const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->field_val_ = header.FieldIds()[field_index].get();
+      break;
+    }
+    case DexFile::kDexAnnotationMethod: {
+      const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->method_val_ = header.MethodIds()[method_index].get();
+      break;
+    }
+    case DexFile::kDexAnnotationArray: {
+      item->annotation_array_val_ = new ArrayItemVector();
+      // Decode all elements.
+      const uint32_t size = DecodeUnsignedLeb128(data);
+      for (uint32_t i = 0; i < size; i++) {
+        item->annotation_array_val_->push_back(
+            std::unique_ptr<ArrayItem>(ReadArrayItem(header, data)));
+      }
+      break;
+    }
+    case DexFile::kDexAnnotationAnnotation: {
+      const uint32_t type_idx = DecodeUnsignedLeb128(data);
+      item->annotation_annotation_val_.string_ = header.TypeIds()[type_idx]->GetStringId();
+      item->annotation_annotation_val_.array_ =
+          new std::vector<std::unique_ptr<ArrayItem::NameValuePair>>();
+      // Decode all name=value pairs.
+      const uint32_t size = DecodeUnsignedLeb128(data);
+      for (uint32_t i = 0; i < size; i++) {
+        const uint32_t name_index = DecodeUnsignedLeb128(data);
+        item->annotation_annotation_val_.array_->push_back(
+            std::unique_ptr<ArrayItem::NameValuePair>(
+                new ArrayItem::NameValuePair(header.StringIds()[name_index].get(),
+                                             ReadArrayItem(header, data))));
+      }
+      break;
+    }
+    case DexFile::kDexAnnotationNull:
+      break;
+    case DexFile::kDexAnnotationBoolean:
+      item->bool_val_ = (length != 0);
+      break;
+    default:
+      break;
+  }
+}
+
+static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) {
+  DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
+  PositionInfoVector& positions = debug_info->GetPositionInfo();
+  positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_)));
+  return false;
+}
+
+static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) {
+  DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
+  LocalInfoVector& locals = debug_info->GetLocalInfo();
+  const char* name = entry.name_ != nullptr ? entry.name_ : "(null)";
+  const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
+  locals.push_back(std::unique_ptr<LocalInfo>(
+      new LocalInfo(name, entry.descriptor_, signature, entry.start_address_,
+                    entry.end_address_, entry.reg_)));
+}
+
+CodeItem* ReadCodeItem(const DexFile& dex_file,
+                       const DexFile::CodeItem& disk_code_item,
+                       Header& header) {
+  uint16_t registers_size = disk_code_item.registers_size_;
+  uint16_t ins_size = disk_code_item.ins_size_;
+  uint16_t outs_size = disk_code_item.outs_size_;
+  uint32_t tries_size = disk_code_item.tries_size_;
+
+  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 insns_size = disk_code_item.insns_size_in_code_units_;
+  uint16_t* insns = new uint16_t[insns_size];
+  memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
+
+  TryItemVector* tries = nullptr;
+  if (tries_size > 0) {
+    tries = new TryItemVector();
+    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 = header.GetTypeIdOrNullPtr(type_index);
+        handlers->push_back(std::unique_ptr<const CatchHandler>(
+            new CatchHandler(type_id, it.GetHandlerAddress())));
+      }
+      TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
+      tries->push_back(std::unique_ptr<const TryItem>(try_item));
+    }
+  }
+  return new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries);
+}
+
+MethodItem* GenerateMethodItem(const DexFile& dex_file,
+                               dex_ir::Header& header,
+                               ClassDataItemIterator& cdii) {
+  MethodId* method_item = header.MethodIds()[cdii.GetMemberIndex()].get();
+  uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+  const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
+  CodeItem* code_item = nullptr;
+  DebugInfoItem* debug_info = nullptr;
+  if (disk_code_item != nullptr) {
+    code_item = ReadCodeItem(dex_file, *disk_code_item, header);
+    code_item->SetOffset(cdii.GetMethodCodeItemOffset());
+    debug_info = code_item->DebugInfo();
+  }
+  if (debug_info != nullptr) {
+    bool is_static = (access_flags & kAccStatic) != 0;
+    dex_file.DecodeDebugLocalInfo(
+        disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info);
+    dex_file.DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info);
+  }
+  return new MethodItem(access_flags, method_item, code_item);
+}
+
+AnnotationSetItem* ReadAnnotationSetItem(const DexFile& dex_file,
+                                         const DexFile::AnnotationSetItem& disk_annotations_item,
+                                         Header& header) {
+  if (disk_annotations_item.size_ == 0) {
+    return nullptr;
+  }
+  AnnotationItemVector* items = new AnnotationItemVector();
+  for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) {
+    const DexFile::AnnotationItem* annotation =
+        dex_file.GetAnnotationItem(&disk_annotations_item, i);
+    if (annotation == nullptr) {
+      continue;
+    }
+    uint8_t visibility = annotation->visibility_;
+    const uint8_t* annotation_data = annotation->annotation_;
+    ArrayItem* array_item =
+        ReadArrayItem(header, &annotation_data, DexFile::kDexAnnotationAnnotation, 0);
+    items->push_back(std::unique_ptr<AnnotationItem>(new AnnotationItem(visibility, array_item)));
+  }
+  return new AnnotationSetItem(items);
+}
+
+ParameterAnnotation* ReadParameterAnnotation(
+    const DexFile& dex_file,
+    MethodId* method_id,
+    const DexFile::AnnotationSetRefList* annotation_set_ref_list,
+    Header& header) {
+  AnnotationSetItemVector* annotations = new AnnotationSetItemVector();
+  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]);
+    annotations->push_back(std::unique_ptr<AnnotationSetItem>(
+        ReadAnnotationSetItem(dex_file, *annotation_set_item, header)));
+  }
+  return new ParameterAnnotation(method_id, annotations);
+}
+
+AnnotationsDirectoryItem* ReadAnnotationsDirectoryItem(
+    const DexFile& dex_file,
+    const DexFile::AnnotationsDirectoryItem* disk_annotations_item,
+    Header& header) {
+  const DexFile::AnnotationSetItem* class_set_item =
+      dex_file.GetClassAnnotationSet(disk_annotations_item);
+  AnnotationSetItem* class_annotation = nullptr;
+  if (class_set_item != nullptr) {
+    class_annotation = ReadAnnotationSetItem(dex_file, *class_set_item, header);
+  }
+  const DexFile::FieldAnnotationsItem* fields =
+      dex_file.GetFieldAnnotations(disk_annotations_item);
+  FieldAnnotationVector* field_annotations = nullptr;
+  if (fields != nullptr) {
+    field_annotations = new FieldAnnotationVector();
+    for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
+      FieldId* field_id = header.FieldIds()[fields[i].field_idx_].get();
+      const DexFile::AnnotationSetItem* field_set_item =
+          dex_file.GetFieldAnnotationSetItem(fields[i]);
+      AnnotationSetItem* annotation_set_item =
+          ReadAnnotationSetItem(dex_file, *field_set_item, header);
+      field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
+          new FieldAnnotation(field_id, annotation_set_item)));
+    }
+  }
+  const DexFile::MethodAnnotationsItem* methods =
+      dex_file.GetMethodAnnotations(disk_annotations_item);
+  MethodAnnotationVector* method_annotations = nullptr;
+  if (methods != nullptr) {
+    method_annotations = new MethodAnnotationVector();
+    for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
+      MethodId* method_id = header.MethodIds()[methods[i].method_idx_].get();
+      const DexFile::AnnotationSetItem* method_set_item =
+          dex_file.GetMethodAnnotationSetItem(methods[i]);
+      AnnotationSetItem* annotation_set_item =
+          ReadAnnotationSetItem(dex_file, *method_set_item, header);
+      method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
+          new MethodAnnotation(method_id, annotation_set_item)));
+    }
+  }
+  const DexFile::ParameterAnnotationsItem* parameters =
+      dex_file.GetParameterAnnotations(disk_annotations_item);
+  ParameterAnnotationVector* parameter_annotations = nullptr;
+  if (parameters != nullptr) {
+    parameter_annotations = new ParameterAnnotationVector();
+    for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
+      MethodId* method_id = header.MethodIds()[parameters[i].method_idx_].get();
+      const DexFile::AnnotationSetRefList* list =
+          dex_file.GetParameterAnnotationSetRefList(&parameters[i]);
+      parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
+          ReadParameterAnnotation(dex_file, method_id, list, header)));
+    }
+  }
+
+  return new AnnotationsDirectoryItem(class_annotation,
+                                      field_annotations,
+                                      method_annotations,
+                                      parameter_annotations);
+}
+
+ClassDef* ReadClassDef(const DexFile& dex_file,
+                       const DexFile::ClassDef& disk_class_def,
+                       Header& header) {
+  const TypeId* class_type = header.TypeIds()[disk_class_def.class_idx_].get();
+  uint32_t access_flags = disk_class_def.access_flags_;
+  const TypeId* superclass = header.GetTypeIdOrNullPtr(disk_class_def.superclass_idx_);
+
+  TypeIdVector* interfaces = nullptr;
+  const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
+  uint32_t interfaces_offset = disk_class_def.interfaces_off_;
+  if (type_list != nullptr) {
+    interfaces = new TypeIdVector();
+    for (uint32_t index = 0; index < type_list->Size(); ++index) {
+      interfaces->push_back(header.TypeIds()[type_list->GetTypeItem(index).type_idx_].get());
+    }
+  }
+  const StringId* source_file = header.GetStringIdOrNullPtr(disk_class_def.source_file_idx_);
+  // Annotations.
+  AnnotationsDirectoryItem* annotations = nullptr;
+  const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
+      dex_file.GetAnnotationsDirectory(disk_class_def);
+  if (disk_annotations_directory_item != nullptr) {
+    annotations = ReadAnnotationsDirectoryItem(dex_file, disk_annotations_directory_item, header);
+    annotations->SetOffset(disk_class_def.annotations_off_);
+  }
+  // Static field initializers.
+  ArrayItemVector* static_values = nullptr;
+  const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
+  if (static_data != nullptr) {
+    uint32_t static_value_count = static_data == nullptr ? 0 : DecodeUnsignedLeb128(&static_data);
+    if (static_value_count > 0) {
+      static_values = new ArrayItemVector();
+      for (uint32_t i = 0; i < static_value_count; ++i) {
+        static_values->push_back(std::unique_ptr<ArrayItem>(ReadArrayItem(header, &static_data)));
+      }
+    }
+  }
+  // Read the fields and methods defined by the class, resolving the circular reference from those
+  // to classes by setting class at the same time.
+  const uint8_t* encoded_data = dex_file.GetClassData(disk_class_def);
+  ClassData* class_data = nullptr;
+  if (encoded_data != nullptr) {
+    uint32_t offset = disk_class_def.class_data_off_;
+    ClassDataItemIterator cdii(dex_file, encoded_data);
+    // Static fields.
+    FieldItemVector* static_fields = new FieldItemVector();
+    for (uint32_t i = 0; cdii.HasNextStaticField(); i++, cdii.Next()) {
+      FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get();
+      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+      static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
+    }
+    // Instance fields.
+    FieldItemVector* instance_fields = new FieldItemVector();
+    for (uint32_t i = 0; cdii.HasNextInstanceField(); i++, cdii.Next()) {
+      FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get();
+      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+      instance_fields->push_back(
+          std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
+    }
+    // Direct methods.
+    MethodItemVector* direct_methods = new MethodItemVector();
+    for (uint32_t i = 0; cdii.HasNextDirectMethod(); i++, cdii.Next()) {
+      direct_methods->push_back(
+          std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, header, cdii)));
+    }
+    // Virtual methods.
+    MethodItemVector* virtual_methods = new MethodItemVector();
+    for (uint32_t i = 0; cdii.HasNextVirtualMethod(); i++, cdii.Next()) {
+      virtual_methods->push_back(
+          std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, header, cdii)));
+    }
+    class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
+    class_data->SetOffset(offset);
+  }
+  return new ClassDef(class_type,
+                      access_flags,
+                      superclass,
+                      interfaces,
+                      interfaces_offset,
+                      source_file,
+                      annotations,
+                      static_values,
+                      class_data);
+}
+
+}  // namespace
+
+Header* DexIrBuilder(const DexFile& dex_file) {
+  const DexFile::Header& disk_header = dex_file.GetHeader();
+  Header* header = new Header(disk_header.magic_,
+                              disk_header.checksum_,
+                              disk_header.signature_,
+                              disk_header.endian_tag_,
+                              disk_header.file_size_,
+                              disk_header.header_size_,
+                              disk_header.link_size_,
+                              disk_header.link_off_,
+                              disk_header.data_size_,
+                              disk_header.data_off_);
+  // Walk the rest of the header fields.
+  // StringId table.
+  std::vector<std::unique_ptr<StringId>>& string_ids = header->StringIds();
+  header->SetStringIdsOffset(disk_header.string_ids_off_);
+  for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
+    const DexFile::StringId& disk_string_id = dex_file.GetStringId(i);
+    StringId* string_id = new StringId(dex_file.GetStringData(disk_string_id));
+    string_id->SetOffset(i);
+    string_ids.push_back(std::unique_ptr<StringId>(string_id));
+  }
+  // TypeId table.
+  std::vector<std::unique_ptr<TypeId>>& type_ids = header->TypeIds();
+  header->SetTypeIdsOffset(disk_header.type_ids_off_);
+  for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
+    const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(i);
+    TypeId* type_id = new TypeId(header->StringIds()[disk_type_id.descriptor_idx_].get());
+    type_id->SetOffset(i);
+    type_ids.push_back(std::unique_ptr<TypeId>(type_id));
+  }
+  // ProtoId table.
+  std::vector<std::unique_ptr<ProtoId>>& proto_ids = header->ProtoIds();
+  header->SetProtoIdsOffset(disk_header.proto_ids_off_);
+  for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
+    const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
+    // Build the parameter type vector.
+    TypeIdVector* parameters = new TypeIdVector();
+    DexFileParameterIterator dfpi(dex_file, disk_proto_id);
+    while (dfpi.HasNext()) {
+      parameters->push_back(header->TypeIds()[dfpi.GetTypeIdx()].get());
+      dfpi.Next();
+    }
+    ProtoId* proto_id = new ProtoId(header->StringIds()[disk_proto_id.shorty_idx_].get(),
+                                    header->TypeIds()[disk_proto_id.return_type_idx_].get(),
+                                    parameters);
+    proto_id->SetOffset(i);
+    proto_ids.push_back(std::unique_ptr<ProtoId>(proto_id));
+  }
+  // FieldId table.
+  std::vector<std::unique_ptr<FieldId>>& field_ids = header->FieldIds();
+  header->SetFieldIdsOffset(disk_header.field_ids_off_);
+  for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
+    const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
+    FieldId* field_id = new FieldId(header->TypeIds()[disk_field_id.class_idx_].get(),
+                                    header->TypeIds()[disk_field_id.type_idx_].get(),
+                                    header->StringIds()[disk_field_id.name_idx_].get());
+    field_id->SetOffset(i);
+    field_ids.push_back(std::unique_ptr<FieldId>(field_id));
+  }
+  // MethodId table.
+  std::vector<std::unique_ptr<MethodId>>& method_ids = header->MethodIds();
+  header->SetMethodIdsOffset(disk_header.method_ids_off_);
+  for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
+    const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
+    MethodId* method_id = new MethodId(header->TypeIds()[disk_method_id.class_idx_].get(),
+                                       header->ProtoIds()[disk_method_id.proto_idx_].get(),
+                                       header->StringIds()[disk_method_id.name_idx_].get());
+    method_id->SetOffset(i);
+    method_ids.push_back(std::unique_ptr<MethodId>(method_id));
+  }
+  // ClassDef table.
+  std::vector<std::unique_ptr<ClassDef>>& class_defs = header->ClassDefs();
+  header->SetClassDefsOffset(disk_header.class_defs_off_);
+  for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
+    const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
+    ClassDef* class_def = ReadClassDef(dex_file, disk_class_def, *header);
+    class_def->SetOffset(i);
+    class_defs.push_back(std::unique_ptr<ClassDef>(class_def));
+  }
+
+  return header;
+}
+
+}  // namespace dex_ir
+}  // namespace art
diff --git a/dexlayout/dex_ir_builder.h b/dexlayout/dex_ir_builder.h
new file mode 100644
index 0000000..c53157b
--- /dev/null
+++ b/dexlayout/dex_ir_builder.h
@@ -0,0 +1,32 @@
+/*
+ * 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_IR_BUILDER_H_
+#define ART_DEXLAYOUT_DEX_IR_BUILDER_H_
+
+#include "dex_ir.h"
+
+namespace art {
+namespace dex_ir {
+
+dex_ir::Header* DexIrBuilder(const DexFile& dex_file);
+
+}  // namespace dex_ir
+}  // namespace art
+
+#endif  // ART_DEXLAYOUT_DEX_IR_BUILDER_H_
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 0b31614..0d0b37a 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -30,7 +30,7 @@
 #include <sstream>
 #include <vector>
 
-#include "dex_ir.h"
+#include "dex_ir_builder.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "utils.h"
@@ -501,20 +501,33 @@
   }
   fprintf(out_file_, "annotations_off     : %d (0x%06x)\n",
           annotations_offset, annotations_offset);
-  fprintf(out_file_, "class_data_off      : %d (0x%06x)\n",
-          class_def->GetClassData()->GetOffset(), class_def->GetClassData()->GetOffset());
+  if (class_def->GetClassData() == nullptr) {
+    fprintf(out_file_, "class_data_off      : %d (0x%06x)\n", 0, 0);
+  } else {
+    fprintf(out_file_, "class_data_off      : %d (0x%06x)\n",
+            class_def->GetClassData()->GetOffset(), class_def->GetClassData()->GetOffset());
+  }
 
   // Fields and methods.
   dex_ir::ClassData* class_data = class_def->GetClassData();
-  if (class_data != nullptr) {
-    fprintf(out_file_, "static_fields_size  : %zu\n", class_data->StaticFields().size());
-    fprintf(out_file_, "instance_fields_size: %zu\n", class_data->InstanceFields().size());
-    fprintf(out_file_, "direct_methods_size : %zu\n", class_data->DirectMethods().size());
-    fprintf(out_file_, "virtual_methods_size: %zu\n", class_data->VirtualMethods().size());
+  if (class_data != nullptr && class_data->StaticFields() != nullptr) {
+    fprintf(out_file_, "static_fields_size  : %zu\n", class_data->StaticFields()->size());
   } else {
     fprintf(out_file_, "static_fields_size  : 0\n");
+  }
+  if (class_data != nullptr && class_data->InstanceFields() != nullptr) {
+    fprintf(out_file_, "instance_fields_size: %zu\n", class_data->InstanceFields()->size());
+  } else {
     fprintf(out_file_, "instance_fields_size: 0\n");
+  }
+  if (class_data != nullptr && class_data->DirectMethods() != nullptr) {
+    fprintf(out_file_, "direct_methods_size : %zu\n", class_data->DirectMethods()->size());
+  } else {
     fprintf(out_file_, "direct_methods_size : 0\n");
+  }
+  if (class_data != nullptr && class_data->VirtualMethods() != nullptr) {
+    fprintf(out_file_, "virtual_methods_size: %zu\n", class_data->VirtualMethods()->size());
+  } else {
     fprintf(out_file_, "virtual_methods_size: 0\n");
   }
   fprintf(out_file_, "\n");
@@ -524,12 +537,11 @@
  * Dumps an annotation set item.
  */
 static void DumpAnnotationSetItem(dex_ir::AnnotationSetItem* set_item) {
-  if (set_item == nullptr || set_item->GetItems().size() == 0) {
+  if (set_item == nullptr || set_item->GetItems()->size() == 0) {
     fputs("  empty-annotation-set\n", out_file_);
     return;
   }
-  for (std::unique_ptr<dex_ir::AnnotationSetItem::AnnotationItem>& annotation :
-       set_item->GetItems()) {
+  for (std::unique_ptr<dex_ir::AnnotationItem>& annotation : *set_item->GetItems()) {
     if (annotation == nullptr) {
       continue;
     }
@@ -561,12 +573,9 @@
   fprintf(out_file_, "Class #%d annotations:\n", idx);
 
   dex_ir::AnnotationSetItem* class_set_item = annotations_directory->GetClassAnnotation();
-  std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::FieldAnnotation>>& fields =
-      annotations_directory->GetFieldAnnotations();
-  std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::MethodAnnotation>>& methods =
-      annotations_directory->GetMethodAnnotations();
-  std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::ParameterAnnotation>>& parameters =
-      annotations_directory->GetParameterAnnotations();
+  dex_ir::FieldAnnotationVector* fields = annotations_directory->GetFieldAnnotations();
+  dex_ir::MethodAnnotationVector* methods = annotations_directory->GetMethodAnnotations();
+  dex_ir::ParameterAnnotationVector* parameters = annotations_directory->GetParameterAnnotations();
 
   // Annotations on the class itself.
   if (class_set_item != nullptr) {
@@ -575,34 +584,40 @@
   }
 
   // Annotations on fields.
-  for (auto& field : fields) {
-    const dex_ir::FieldId* field_id = field->GetFieldId();
-    const uint32_t field_idx = field_id->GetOffset();
-    const char* field_name = field_id->Name()->Data();
-    fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name);
-    DumpAnnotationSetItem(field->GetAnnotationSetItem());
+  if (fields != nullptr) {
+    for (auto& field : *fields) {
+      const dex_ir::FieldId* field_id = field->GetFieldId();
+      const uint32_t field_idx = field_id->GetOffset();
+      const char* field_name = field_id->Name()->Data();
+      fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name);
+      DumpAnnotationSetItem(field->GetAnnotationSetItem());
+    }
   }
 
   // Annotations on methods.
-  for (auto& method : methods) {
-    const dex_ir::MethodId* method_id = method->GetMethodId();
-    const uint32_t method_idx = method_id->GetOffset();
-    const char* method_name = method_id->Name()->Data();
-    fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name);
-    DumpAnnotationSetItem(method->GetAnnotationSetItem());
+  if (methods != nullptr) {
+    for (auto& method : *methods) {
+      const dex_ir::MethodId* method_id = method->GetMethodId();
+      const uint32_t method_idx = method_id->GetOffset();
+      const char* method_name = method_id->Name()->Data();
+      fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name);
+      DumpAnnotationSetItem(method->GetAnnotationSetItem());
+    }
   }
 
   // Annotations on method parameters.
-  for (auto& parameter : parameters) {
-    const dex_ir::MethodId* method_id = parameter->GetMethodId();
-    const uint32_t method_idx = method_id->GetOffset();
-    const char* method_name = method_id->Name()->Data();
-    fprintf(out_file_, "Annotations on method #%u '%s' parameters\n", method_idx, method_name);
-    uint32_t j = 0;
-    for (auto& annotation : parameter->GetAnnotations()) {
-      fprintf(out_file_, "#%u\n", j);
-      DumpAnnotationSetItem(annotation.get());
-      ++j;
+  if (parameters != nullptr) {
+    for (auto& parameter : *parameters) {
+      const dex_ir::MethodId* method_id = parameter->GetMethodId();
+      const uint32_t method_idx = method_id->GetOffset();
+      const char* method_name = method_id->Name()->Data();
+      fprintf(out_file_, "Annotations on method #%u '%s' parameters\n", method_idx, method_name);
+      uint32_t j = 0;
+      for (auto& annotation : *parameter->GetAnnotations()) {
+        fprintf(out_file_, "#%u\n", j);
+        DumpAnnotationSetItem(annotation.get());
+        ++j;
+      }
     }
   }
 
@@ -612,7 +627,7 @@
 /*
  * Dumps an interface that a class declares to implement.
  */
-static void DumpInterface(dex_ir::TypeId* type_item, int i) {
+static void DumpInterface(const dex_ir::TypeId* type_item, int i) {
   const char* interface_name = type_item->GetStringId()->Data();
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "    #%d              : '%s'\n", i, interface_name);
@@ -1260,8 +1275,8 @@
   }
   while (it.HasNextVirtualMethod()) {
     DumpCFG(dex_file,
-                it.GetMemberIndex(),
-                it.GetMethodCodeItem());
+            it.GetMemberIndex(),
+            it.GetMethodCodeItem());
     it.Next();
   }
 }
@@ -1274,7 +1289,10 @@
  * If "*last_package" is nullptr or does not match the current class' package,
  * the value will be replaced with a newly-allocated string.
  */
-static void DumpClass(dex_ir::Header* header, int idx, char** last_package) {
+static void DumpClass(const DexFile* dex_file,
+                      dex_ir::Header* header,
+                      int idx,
+                      char** last_package) {
   dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
   // Omitting non-public class.
   if (options_.exports_only_ && (class_def->GetAccessFlags() & kAccPublic) == 0) {
@@ -1290,7 +1308,7 @@
   }
 
   if (options_.show_cfg_) {
-    DumpCFG(&header->GetDexFile(), idx);
+    DumpCFG(dex_file, idx);
     return;
   }
 
@@ -1368,10 +1386,12 @@
   }
 
   // Interfaces.
-  std::vector<dex_ir::TypeId*>* interfaces = class_def->Interfaces();
-  for (uint32_t i = 0; i < interfaces->size(); i++) {
-    DumpInterface((*interfaces)[i], i);
-  }  // for
+  dex_ir::TypeIdVector* interfaces = class_def->Interfaces();
+  if (interfaces != nullptr) {
+    for (uint32_t i = 0; i < interfaces->size(); i++) {
+      DumpInterface((*interfaces)[i], i);
+    }  // for
+  }
 
   // Fields and methods.
   dex_ir::ClassData* class_data = class_def->GetClassData();
@@ -1383,52 +1403,68 @@
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Static fields     -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::FieldItem>>& static_fields = class_data->StaticFields();
-  for (uint32_t i = 0; i < static_fields.size(); i++) {
-    DumpSField(header,
-               static_fields[i]->GetFieldId()->GetOffset(),
-               static_fields[i]->GetAccessFlags(),
-               i,
-               i < static_values_size ? (*static_values)[i].get() : nullptr);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::FieldItemVector* static_fields = class_data->StaticFields();
+    if (static_fields != nullptr) {
+      for (uint32_t i = 0; i < static_fields->size(); i++) {
+        DumpSField(header,
+                   (*static_fields)[i]->GetFieldId()->GetOffset(),
+                   (*static_fields)[i]->GetAccessFlags(),
+                   i,
+                   i < static_values_size ? (*static_values)[i].get() : nullptr);
+      }  // for
+    }
+  }
 
   // Instance fields.
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Instance fields   -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::FieldItem>>& instance_fields = class_data->InstanceFields();
-  for (uint32_t i = 0; i < instance_fields.size(); i++) {
-    DumpIField(header,
-               instance_fields[i]->GetFieldId()->GetOffset(),
-               instance_fields[i]->GetAccessFlags(),
-               i);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::FieldItemVector* instance_fields = class_data->InstanceFields();
+    if (instance_fields != nullptr) {
+      for (uint32_t i = 0; i < instance_fields->size(); i++) {
+        DumpIField(header,
+                   (*instance_fields)[i]->GetFieldId()->GetOffset(),
+                   (*instance_fields)[i]->GetAccessFlags(),
+                   i);
+      }  // for
+    }
+  }
 
   // Direct methods.
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Direct methods    -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::MethodItem>>& direct_methods = class_data->DirectMethods();
-  for (uint32_t i = 0; i < direct_methods.size(); i++) {
-    DumpMethod(header,
-               direct_methods[i]->GetMethodId()->GetOffset(),
-               direct_methods[i]->GetAccessFlags(),
-               direct_methods[i]->GetCodeItem(),
-               i);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::MethodItemVector* direct_methods = class_data->DirectMethods();
+    if (direct_methods != nullptr) {
+      for (uint32_t i = 0; i < direct_methods->size(); i++) {
+        DumpMethod(header,
+                   (*direct_methods)[i]->GetMethodId()->GetOffset(),
+                   (*direct_methods)[i]->GetAccessFlags(),
+                   (*direct_methods)[i]->GetCodeItem(),
+                 i);
+      }  // for
+    }
+  }
 
   // Virtual methods.
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "  Virtual methods   -\n");
   }
-  std::vector<std::unique_ptr<dex_ir::MethodItem>>& virtual_methods = class_data->VirtualMethods();
-  for (uint32_t i = 0; i < virtual_methods.size(); i++) {
-    DumpMethod(header,
-               virtual_methods[i]->GetMethodId()->GetOffset(),
-               virtual_methods[i]->GetAccessFlags(),
-               virtual_methods[i]->GetCodeItem(),
-               i);
-  }  // for
+  if (class_data != nullptr) {
+    dex_ir::MethodItemVector* virtual_methods = class_data->VirtualMethods();
+    if (virtual_methods != nullptr) {
+      for (uint32_t i = 0; i < virtual_methods->size(); i++) {
+        DumpMethod(header,
+                   (*virtual_methods)[i]->GetMethodId()->GetOffset(),
+                   (*virtual_methods)[i]->GetAccessFlags(),
+                   (*virtual_methods)[i]->GetCodeItem(),
+                   i);
+      }  // for
+    }
+  }
 
   // End of class.
   if (options_.output_format_ == kOutputPlain) {
@@ -1454,11 +1490,11 @@
     fprintf(out_file_, "Opened '%s', DEX version '%.3s'\n",
             file_name, dex_file->GetHeader().magic_ + 4);
   }
-  dex_ir::Header header(*dex_file);
+  dex_ir::Header* header = dex_ir::DexIrBuilder(*dex_file);
 
   // Headers.
   if (options_.show_file_headers_) {
-    DumpFileHeader(&header);
+    DumpFileHeader(header);
   }
 
   // Open XML context.
@@ -1468,9 +1504,9 @@
 
   // Iterate over all classes.
   char* package = nullptr;
-  const uint32_t class_defs_size = header.ClassDefsSize();
+  const uint32_t class_defs_size = header->ClassDefsSize();
   for (uint32_t i = 0; i < class_defs_size; i++) {
-    DumpClass(&header, i, &package);
+    DumpClass(dex_file, header, i, &package);
   }  // for
 
   // Free the last package allocated.