Merge "Fix missing entry for the static libdexfile_support test in the gtest list."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index e28ce2b..f621bcb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -53,6 +53,12 @@
 # Old Android Runtime APEX package, before the introduction of "release" and "debug" packages.
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex/com.android.runtime.apex)
 
+# Clean up ICU libraries moved to runtime apex
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib*/libandroidicu.so)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib*/libpac.so)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/nativetest*/art_libdexfile_support_tests/dex_file_supp_test)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 533f61c..4db2066 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -111,11 +111,20 @@
 
 // Native libraries that support the core Java libraries.
 libcore_native_shared_libs = [
+    "libandroidicu",
+    "libexpat",
+    "libicui18n",
+    "libicuuc",
     "libjavacore",
     "libopenjdk",
-    "libexpat",
     "libz",
-    "libziparchive"
+    "libziparchive",
+]
+
+libcore_native_device_only_shared_libs = libcore_native_shared_libs + [
+    // TODO(b/122876336): Remove libpac.so once it's migrated to Webview.
+    // libpac is used by frameworks, not by ART host.
+    "libpac",
 ]
 
 // Temporary library includes for b/123591866 as all libraries are moved into the main art-apex.
@@ -162,7 +171,7 @@
     java_libs: libcore_java_libs,
     native_shared_libs: art_runtime_base_native_shared_libs
         + bionic_native_shared_libs
-        + libcore_native_shared_libs,
+        + libcore_native_device_only_shared_libs,
     multilib: {
         both: {
             // TODO: Add logic to create a `dalvikvm` symlink to `dalvikvm32` or `dalvikvm64`
@@ -194,7 +203,7 @@
     native_shared_libs: art_runtime_base_native_shared_libs
         + art_runtime_debug_native_shared_libs
         + bionic_native_shared_libs
-        + libcore_native_shared_libs
+        + libcore_native_device_only_shared_libs
         + libcore_debug_native_shared_libs,
     multilib: {
         both: {
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index 84013f6..46d1e4e 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -396,7 +396,11 @@
 
   def run(self):
     # Check that the mounted image contains Android Core libraries.
+    self._checker.check_library('libandroidicu.so')
     self._checker.check_library('libexpat.so')
+    self._checker.check_library('libicui18n.so')
+    self._checker.check_library('libicuuc.so')
+    self._checker.check_library('libpac.so')
     self._checker.check_library('libz.so')
 
 class ReleaseHostChecker:
@@ -407,7 +411,10 @@
 
   def run(self):
     # Check that the mounted image contains Android Core libraries.
+    self._checker.check_library('libandroidicu-host.so')
     self._checker.check_library('libexpat-host.so')
+    self._checker.check_library('libicui18n-host.so')
+    self._checker.check_library('libicuuc-host.so')
     self._checker.check_library('libz-host.so')
 
 class DebugChecker:
diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt
index 3cfda65..f624bd1 100644
--- a/build/apex/ld.config.txt
+++ b/build/apex/ld.config.txt
@@ -34,6 +34,11 @@
 namespace.platform.link.default.shared_libs += libnativebridge.so
 namespace.platform.link.default.shared_libs += libnativehelper.so
 namespace.platform.link.default.shared_libs += libnativeloader.so
+namespace.platform.link.default.shared_libs += libandroidicu.so
+
+# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
+namespace.platform.link.default.shared_libs += libpac.so
+
 # /system/lib/libc.so, etc are symlinks to /bionic/lib/libc.so, etc.
 # Add /bionic/lib to the permitted paths because linker uses realpath(3)
 # to check the accessibility of the lib. We could add this to search.paths
diff --git a/compiler/debug/dwarf/headers.h b/compiler/debug/dwarf/headers.h
index 869a2c2..3cc8ad8 100644
--- a/compiler/debug/dwarf/headers.h
+++ b/compiler/debug/dwarf/headers.h
@@ -90,30 +90,6 @@
   writer.UpdateUint32(fde_header_start, writer.data()->size() - fde_header_start - 4);
 }
 
-// Read singe FDE entry from 'data' (which is advanced).
-template<typename Addr>
-bool ReadFDE(const uint8_t** data, Addr* addr, Addr* size, ArrayRef<const uint8_t>* opcodes) {
-  struct Header {
-    uint32_t length;
-    int32_t cie_pointer;
-    Addr addr;
-    Addr size;
-    uint8_t augmentaion;
-    uint8_t opcodes[];
-  } PACKED(1);
-  const Header* header = reinterpret_cast<const Header*>(*data);
-  const size_t length = 4 + header->length;
-  *data += length;
-  if (header->cie_pointer == -1) {
-    return false;  // Not an FDE entry.
-  }
-  DCHECK_EQ(header->cie_pointer, 0);  // Expects single CIE. Assumes DW_DEBUG_FRAME_FORMAT.
-  *addr = header->addr;
-  *size = header->size;
-  *opcodes = ArrayRef<const uint8_t>(header->opcodes, length - offsetof(Header, opcodes));
-  return true;
-}
-
 // Write compilation unit (CU) to .debug_info section.
 template<typename Vector>
 void WriteDebugInfoCU(uint32_t debug_abbrev_offset,
diff --git a/compiler/debug/elf_debug_reader.h b/compiler/debug/elf_debug_reader.h
index 91b1b3e..1820e7c 100644
--- a/compiler/debug/elf_debug_reader.h
+++ b/compiler/debug/elf_debug_reader.h
@@ -22,6 +22,9 @@
 #include "elf.h"
 #include "xz_utils.h"
 
+#include <map>
+#include <string_view>
+
 namespace art {
 namespace debug {
 
@@ -29,75 +32,141 @@
 //
 // It is the bare minimum needed to read mini-debug-info symbols for unwinding.
 // We use it to merge JIT mini-debug-infos together or to prune them after GC.
-// The consumed ELF file comes from ART JIT.
-template <typename ElfTypes, typename VisitSym, typename VisitFde>
-static void ReadElfSymbols(const uint8_t* elf, VisitSym visit_sym, VisitFde visit_fde) {
+template <typename ElfTypes>
+class ElfDebugReader {
+ public:
   // Note that the input buffer might be misaligned.
   typedef typename ElfTypes::Ehdr ALIGNED(1) Elf_Ehdr;
   typedef typename ElfTypes::Shdr ALIGNED(1) Elf_Shdr;
   typedef typename ElfTypes::Sym ALIGNED(1) Elf_Sym;
   typedef typename ElfTypes::Addr ALIGNED(1) Elf_Addr;
 
-  // Read and check the elf header.
-  const Elf_Ehdr* header = reinterpret_cast<const Elf_Ehdr*>(elf);
-  CHECK(header->checkMagic());
+  // Call Frame Information.
+  struct CFI {
+    uint32_t length;  // Length excluding the size of this field.
+    int32_t cie_pointer;  // Offset in the section or -1 for CIE.
 
-  // Find sections that we are interested in.
-  const Elf_Shdr* sections = reinterpret_cast<const Elf_Shdr*>(elf + header->e_shoff);
-  const Elf_Shdr* strtab = nullptr;
-  const Elf_Shdr* symtab = nullptr;
-  const Elf_Shdr* debug_frame = nullptr;
-  const Elf_Shdr* gnu_debugdata = nullptr;
-  for (size_t i = 1 /* skip null section */; i < header->e_shnum; i++) {
-    const Elf_Shdr* section = sections + i;
-    const char* name = reinterpret_cast<const char*>(
-        elf + sections[header->e_shstrndx].sh_offset + section->sh_name);
-    if (strcmp(name, ".strtab") == 0) {
-      strtab = section;
-    } else if (strcmp(name, ".symtab") == 0) {
-      symtab = section;
-    } else if (strcmp(name, ".debug_frame") == 0) {
-      debug_frame = section;
-    } else if (strcmp(name, ".gnu_debugdata") == 0) {
-      gnu_debugdata = section;
+    const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(this); }
+    size_t size() const { return sizeof(uint32_t) + length; }
+  } PACKED(1);
+
+  // Common Information Entry.
+  struct CIE : public CFI {
+  } PACKED(1);
+
+  // Frame Description Entry.
+  struct FDE : public CFI {
+    Elf_Addr sym_addr;
+    Elf_Addr sym_size;
+  } PACKED(1);
+
+  explicit ElfDebugReader(ArrayRef<const uint8_t> file) : file_(file) {
+    header_ = Read<Elf_Ehdr>(/*offset=*/ 0);
+    CHECK(header_->checkMagic());
+    CHECK_EQ(header_->e_ehsize, sizeof(Elf_Ehdr));
+    CHECK_EQ(header_->e_shentsize, sizeof(Elf_Shdr));
+
+    // Find all ELF sections.
+    sections_ = Read<Elf_Shdr>(header_->e_shoff, header_->e_shnum);
+    for (const Elf_Shdr& section : sections_) {
+      const char* name = Read<char>(sections_[header_->e_shstrndx].sh_offset + section.sh_name);
+      section_map_[std::string_view(name)] = &section;
+    }
+
+    // Decompressed embedded debug symbols, if any.
+    const Elf_Shdr* gnu_debugdata = section_map_[".gnu_debugdata"];
+    if (gnu_debugdata != nullptr) {
+      auto compressed = Read<uint8_t>(gnu_debugdata->sh_offset, gnu_debugdata->sh_size);
+      XzDecompress(compressed, &decompressed_gnu_debugdata_);
+      gnu_debugdata_reader_.reset(new ElfDebugReader(decompressed_gnu_debugdata_));
     }
   }
 
-  // Visit symbols.
-  if (symtab != nullptr && strtab != nullptr) {
-    const Elf_Sym* symbols = reinterpret_cast<const Elf_Sym*>(elf + symtab->sh_offset);
-    DCHECK_EQ(symtab->sh_entsize, sizeof(Elf_Sym));
-    size_t count = symtab->sh_size / sizeof(Elf_Sym);
-    for (size_t i = 1 /* skip null symbol */; i < count; i++) {
-      Elf_Sym symbol = symbols[i];
-      if (symbol.getBinding() != STB_LOCAL) {  // Ignore local symbols (e.g. "$t").
-        const uint8_t* name = elf + strtab->sh_offset + symbol.st_name;
-        visit_sym(symbol, reinterpret_cast<const char*>(name));
+  explicit ElfDebugReader(std::vector<uint8_t>& file)
+      : ElfDebugReader(ArrayRef<const uint8_t>(file)) {
+  }
+
+  const Elf_Ehdr* GetHeader() { return header_; }
+
+  ArrayRef<Elf_Shdr> GetSections() { return sections_; }
+
+  const Elf_Shdr* GetSection(const char* name) { return section_map_[name]; }
+
+  template <typename VisitSym>
+  void VisitFunctionSymbols(VisitSym visit_sym) {
+    const Elf_Shdr* symtab = GetSection(".symtab");
+    const Elf_Shdr* strtab = GetSection(".strtab");
+    const Elf_Shdr* text = GetSection(".text");
+    if (symtab != nullptr && strtab != nullptr) {
+      CHECK_EQ(symtab->sh_entsize, sizeof(Elf_Sym));
+      size_t count = symtab->sh_size / sizeof(Elf_Sym);
+      for (const Elf_Sym& symbol : Read<Elf_Sym>(symtab->sh_offset, count)) {
+        if (symbol.getType() == STT_FUNC && &sections_[symbol.st_shndx] == text) {
+          visit_sym(symbol, Read<char>(strtab->sh_offset + symbol.st_name));
+        }
+      }
+    }
+    if (gnu_debugdata_reader_ != nullptr) {
+      gnu_debugdata_reader_->VisitFunctionSymbols(visit_sym);
+    }
+  }
+
+  template <typename VisitSym>
+  void VisitDynamicSymbols(VisitSym visit_sym) {
+    const Elf_Shdr* dynsym = GetSection(".dynsym");
+    const Elf_Shdr* dynstr = GetSection(".dynstr");
+    if (dynsym != nullptr && dynstr != nullptr) {
+      CHECK_EQ(dynsym->sh_entsize, sizeof(Elf_Sym));
+      size_t count = dynsym->sh_size / sizeof(Elf_Sym);
+      for (const Elf_Sym& symbol : Read<Elf_Sym>(dynsym->sh_offset, count)) {
+        visit_sym(symbol, Read<char>(dynstr->sh_offset + symbol.st_name));
       }
     }
   }
 
-  // Visit CFI (unwind) data.
-  if (debug_frame != nullptr) {
-    const uint8_t* data = elf + debug_frame->sh_offset;
-    const uint8_t* end = data + debug_frame->sh_size;
-    while (data < end) {
-      Elf_Addr addr, size;
-      ArrayRef<const uint8_t> opcodes;
-      if (dwarf::ReadFDE<Elf_Addr>(&data, &addr, &size, &opcodes)) {
-        visit_fde(addr, size, opcodes);
+  template <typename VisitCIE, typename VisitFDE>
+  void VisitDebugFrame(VisitCIE visit_cie, VisitFDE visit_fde) {
+    const Elf_Shdr* debug_frame = GetSection(".debug_frame");
+    if (debug_frame != nullptr) {
+      for (size_t offset = 0; offset < debug_frame->sh_size;) {
+        const CFI* entry = Read<CFI>(debug_frame->sh_offset + offset);
+        DCHECK_LE(entry->size(), debug_frame->sh_size - offset);
+        if (entry->cie_pointer == -1) {
+          visit_cie(Read<CIE>(debug_frame->sh_offset + offset));
+        } else {
+          const FDE* fde = Read<FDE>(debug_frame->sh_offset + offset);
+          visit_fde(fde, Read<CIE>(debug_frame->sh_offset + fde->cie_pointer));
+        }
+        offset += entry->size();
       }
     }
+    if (gnu_debugdata_reader_ != nullptr) {
+      gnu_debugdata_reader_->VisitDebugFrame(visit_cie, visit_fde);
+    }
   }
 
-  // Process embedded compressed ELF file.
-  if (gnu_debugdata != nullptr) {
-    ArrayRef<const uint8_t> compressed(elf + gnu_debugdata->sh_offset, gnu_debugdata->sh_size);
-    std::vector<uint8_t> decompressed;
-    XzDecompress(compressed, &decompressed);
-    ReadElfSymbols<ElfTypes>(decompressed.data(), visit_sym, visit_fde);
+ private:
+  template<typename T>
+  const T* Read(size_t offset) {
+    DCHECK_LE(offset + sizeof(T), file_.size());
+    return reinterpret_cast<const T*>(file_.data() + offset);
   }
-}
+
+  template<typename T>
+  ArrayRef<const T> Read(size_t offset, size_t count) {
+    DCHECK_LE(offset + count * sizeof(T), file_.size());
+    return ArrayRef<const T>(Read<T>(offset), count);
+  }
+
+  ArrayRef<const uint8_t> const file_;
+  const Elf_Ehdr* header_;
+  ArrayRef<const Elf_Shdr> sections_;
+  std::unordered_map<std::string_view, const Elf_Shdr*> section_map_;
+  std::vector<uint8_t> decompressed_gnu_debugdata_;
+  std::unique_ptr<ElfDebugReader> gnu_debugdata_reader_;
+
+  DISALLOW_COPY_AND_ASSIGN(ElfDebugReader);
+};
 
 }  // namespace debug
 }  // namespace art
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc
index fd638b7..3b7363b 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -203,25 +203,26 @@
   // Verify the ELF file by reading it back using the trivial reader.
   if (kIsDebugBuild) {
     using Elf_Sym = typename ElfTypes::Sym;
-    using Elf_Addr = typename ElfTypes::Addr;
     size_t num_syms = 0;
-    size_t num_cfis = 0;
-    ReadElfSymbols<ElfTypes>(
-        buffer.data(),
-        [&](Elf_Sym sym, const char*) {
-          DCHECK_EQ(sym.st_value, method_info.code_address + CompiledMethod::CodeDelta(isa));
-          DCHECK_EQ(sym.st_size, method_info.code_size);
-          num_syms++;
-        },
-        [&](Elf_Addr addr, Elf_Addr size, ArrayRef<const uint8_t> opcodes) {
-          DCHECK_EQ(addr, method_info.code_address);
-          DCHECK_EQ(size, method_info.code_size);
-          DCHECK_GE(opcodes.size(), method_info.cfi.size());
-          DCHECK_EQ(memcmp(opcodes.data(), method_info.cfi.data(), method_info.cfi.size()), 0);
-          num_cfis++;
-        });
+    size_t num_cies = 0;
+    size_t num_fdes = 0;
+    using Reader = ElfDebugReader<ElfTypes>;
+    Reader reader(buffer);
+    reader.VisitFunctionSymbols([&](Elf_Sym sym, const char*) {
+      DCHECK_EQ(sym.st_value, method_info.code_address + CompiledMethod::CodeDelta(isa));
+      DCHECK_EQ(sym.st_size, method_info.code_size);
+      num_syms++;
+    });
+    reader.VisitDebugFrame([&](const Reader::CIE* cie ATTRIBUTE_UNUSED) {
+      num_cies++;
+    }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) {
+      DCHECK_EQ(fde->sym_addr, method_info.code_address);
+      DCHECK_EQ(fde->sym_size, method_info.code_size);
+      num_fdes++;
+    });
     DCHECK_EQ(num_syms, 1u);
-    DCHECK_EQ(num_cfis, 1u);
+    DCHECK_LE(num_cies, 1u);
+    DCHECK_LE(num_fdes, 1u);
   }
   return buffer;
 }
@@ -230,14 +231,13 @@
 std::vector<uint8_t> PackElfFileForJIT(
     InstructionSet isa,
     const InstructionSetFeatures* features,
-    std::vector<const uint8_t*>& added_elf_files,
+    std::vector<ArrayRef<const uint8_t>>& added_elf_files,
     std::vector<const void*>& removed_symbols,
     /*out*/ size_t* num_symbols) {
   using ElfTypes = ElfRuntimeTypes;
   using Elf_Addr = typename ElfTypes::Addr;
   using Elf_Sym = typename ElfTypes::Sym;
   CHECK_EQ(sizeof(Elf_Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
-  const bool is64bit = Is64BitInstructionSet(isa);
   auto is_removed_symbol = [&removed_symbols](Elf_Addr addr) {
     const void* code_ptr = reinterpret_cast<const void*>(addr);
     return std::binary_search(removed_symbols.begin(), removed_symbols.end(), code_ptr);
@@ -259,35 +259,26 @@
     auto* symtab = builder->GetSymTab();
     auto* debug_frame = builder->GetDebugFrame();
     std::deque<Elf_Sym> symbols;
-    std::vector<uint8_t> debug_frame_buffer;
-    WriteCIE(isa, &debug_frame_buffer);
+
+    using Reader = ElfDebugReader<ElfTypes>;
+    std::deque<Reader> readers;
+    for (ArrayRef<const uint8_t> added_elf_file : added_elf_files) {
+      readers.emplace_back(added_elf_file);
+    }
 
     // Write symbols names. All other data is buffered.
     strtab->Start();
     strtab->Write("");  // strtab should start with empty string.
-    for (const uint8_t* added_elf_file : added_elf_files) {
-      ReadElfSymbols<ElfTypes>(
-          added_elf_file,
-          [&](Elf_Sym sym, const char* name) {
-              if (is_removed_symbol(sym.st_value)) {
-                return;
-              }
-              sym.st_name = strtab->Write(name);
-              symbols.push_back(sym);
-              min_address = std::min<uint64_t>(min_address, sym.st_value);
-              max_address = std::max<uint64_t>(max_address, sym.st_value + sym.st_size);
-          },
-          [&](Elf_Addr addr, Elf_Addr size, ArrayRef<const uint8_t> opcodes) {
-              if (is_removed_symbol(addr)) {
-                return;
-              }
-              dwarf::WriteFDE(is64bit,
-                              /* cie_pointer= */ 0,
-                              addr,
-                              size,
-                              opcodes,
-                              &debug_frame_buffer);
-          });
+    for (Reader& reader : readers) {
+      reader.VisitFunctionSymbols([&](Elf_Sym sym, const char* name) {
+          if (is_removed_symbol(sym.st_value)) {
+            return;
+          }
+          sym.st_name = strtab->Write(name);
+          symbols.push_back(sym);
+          min_address = std::min<uint64_t>(min_address, sym.st_value);
+          max_address = std::max<uint64_t>(max_address, sym.st_value + sym.st_size);
+      });
     }
     strtab->End();
 
@@ -305,7 +296,22 @@
 
     // Add the CFI/unwind section.
     debug_frame->Start();
-    debug_frame->WriteFully(debug_frame_buffer.data(), debug_frame_buffer.size());
+    // ART always produces the same CIE, so we copy the first one and ignore the rest.
+    bool copied_cie = false;
+    for (Reader& reader : readers) {
+      reader.VisitDebugFrame([&](const Reader::CIE* cie) {
+        if (!copied_cie) {
+          debug_frame->WriteFully(cie->data(), cie->size());
+          copied_cie = true;
+        }
+      }, [&](const Reader::FDE* fde, const Reader::CIE* cie ATTRIBUTE_UNUSED) {
+        DCHECK(copied_cie);
+        DCHECK_EQ(fde->cie_pointer, 0);
+        if (!is_removed_symbol(fde->sym_addr)) {
+          debug_frame->WriteFully(fde->data(), fde->size());
+        }
+      });
+    }
     debug_frame->End();
 
     builder->End();
diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h
index 3cc38a2..90580b4 100644
--- a/compiler/debug/elf_debug_writer.h
+++ b/compiler/debug/elf_debug_writer.h
@@ -57,7 +57,7 @@
 std::vector<uint8_t> PackElfFileForJIT(
     InstructionSet isa,
     const InstructionSetFeatures* features,
-    std::vector<const uint8_t*>& added_elf_files,
+    std::vector<ArrayRef<const uint8_t>>& added_elf_files,
     std::vector<const void*>& removed_symbols,
     /*out*/ size_t* num_symbols);
 
diff --git a/compiler/debug/xz_utils.cc b/compiler/debug/xz_utils.cc
index a8f60ac..5b36209 100644
--- a/compiler/debug/xz_utils.cc
+++ b/compiler/debug/xz_utils.cc
@@ -43,12 +43,14 @@
   });
 }
 
-static void XzCompressChunk(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst) {
+void XzCompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst) {
   // Configure the compression library.
   XzInitCrc();
   CLzma2EncProps lzma2Props;
   Lzma2EncProps_Init(&lzma2Props);
   lzma2Props.lzmaProps.level = 1;  // Fast compression.
+  lzma2Props.lzmaProps.reduceSize = src.size();  // Size of data that will be compressed.
+  lzma2Props.blockSize = kChunkSize;
   Lzma2EncProps_Normalize(&lzma2Props);
   CXzProps props;
   XzProps_Init(&props);
@@ -85,69 +87,6 @@
   // Compress.
   SRes res = Xz_Encode(&callbacks, &callbacks, &props, &callbacks);
   CHECK_EQ(res, SZ_OK);
-}
-
-// Compress data while splitting it to smaller chunks to enable random-access reads.
-// The XZ file format supports this well, but the compression library does not.
-// Therefore compress the chunks separately and then glue them together manually.
-//
-// The XZ file format is described here: https://tukaani.org/xz/xz-file-format.txt
-// In short, the file format is: [header] [compressed_block]* [index] [footer]
-// Where [index] is: [num_records] ([compressed_size] [uncompressed_size])* [crc32]
-//
-void XzCompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst) {
-  uint8_t header[] = { 0xFD, '7', 'z', 'X', 'Z', 0, 0, 1, 0x69, 0x22, 0xDE, 0x36 };
-  uint8_t footer[] = { 0, 1, 'Y', 'Z' };
-  dst->insert(dst->end(), header, header + sizeof(header));
-  std::vector<uint8_t> tmp;
-  std::vector<uint32_t> index;
-  for (size_t offset = 0; offset < src.size(); offset += kChunkSize) {
-    size_t size = std::min(src.size() - offset, kChunkSize);
-    tmp.clear();
-    XzCompressChunk(src.SubArray(offset, size), &tmp);
-    DCHECK_EQ(memcmp(tmp.data(), header, sizeof(header)), 0);
-    DCHECK_EQ(memcmp(tmp.data() + tmp.size() - sizeof(footer), footer, sizeof(footer)), 0);
-    uint32_t* index_size = reinterpret_cast<uint32_t*>(tmp.data() + tmp.size() - 8);
-    DCHECK_ALIGNED(index_size, sizeof(uint32_t));
-    size_t index_offset = tmp.size() - 16 - *index_size * 4;
-    const uint8_t* index_ptr = tmp.data() + index_offset;
-    uint8_t index_indicator = *(index_ptr++);
-    CHECK_EQ(index_indicator, 0);  // Mark the start of index (as opposed to compressed block).
-    uint32_t num_records = DecodeUnsignedLeb128(&index_ptr);
-    for (uint32_t i = 0; i < num_records; i++) {
-      index.push_back(DecodeUnsignedLeb128(&index_ptr));  // Compressed size.
-      index.push_back(DecodeUnsignedLeb128(&index_ptr));  // Uncompressed size.
-    }
-    // Copy the raw compressed block(s) located between the header and index.
-    dst->insert(dst->end(), tmp.data() + sizeof(header), tmp.data() + index_offset);
-  }
-
-  // Write the index.
-  uint32_t index_size_in_words;
-  {
-    tmp.clear();
-    dwarf::Writer<> writer(&tmp);
-    writer.PushUint8(0);  // Index indicator.
-    writer.PushUleb128(static_cast<uint32_t>(index.size()) / 2);  // Record count.
-    for (uint32_t i : index) {
-      writer.PushUleb128(i);
-    }
-    writer.Pad(4);
-    index_size_in_words = writer.size() / sizeof(uint32_t);
-    writer.PushUint32(CrcCalc(tmp.data(), tmp.size()));
-    dst->insert(dst->end(), tmp.begin(), tmp.end());
-  }
-
-  // Write the footer.
-  {
-    tmp.clear();
-    dwarf::Writer<> writer(&tmp);
-    writer.PushUint32(0);  // CRC placeholder.
-    writer.PushUint32(index_size_in_words);
-    writer.PushData(footer, sizeof(footer));
-    writer.UpdateUint32(0, CrcCalc(tmp.data() + 4, 6));
-    dst->insert(dst->end(), tmp.begin(), tmp.end());
-  }
 
   // Decompress the data back and check that we get the original.
   if (kIsDebugBuild) {
diff --git a/compiler/optimizing/gvn.cc b/compiler/optimizing/gvn.cc
index 3689d1d..e8460a8 100644
--- a/compiler/optimizing/gvn.cc
+++ b/compiler/optimizing/gvn.cc
@@ -43,7 +43,6 @@
         buckets_(allocator->AllocArray<Node*>(num_buckets_, kArenaAllocGvn)),
         buckets_owned_(allocator, num_buckets_, false, kArenaAllocGvn),
         num_entries_(0u) {
-    // ArenaAllocator returns zeroed memory, so no need to set buckets to null.
     DCHECK(IsPowerOfTwo(num_buckets_));
     std::fill_n(buckets_, num_buckets_, nullptr);
     buckets_owned_.SetInitialBits(num_buckets_);
@@ -57,8 +56,6 @@
         buckets_(allocator->AllocArray<Node*>(num_buckets_, kArenaAllocGvn)),
         buckets_owned_(allocator, num_buckets_, false, kArenaAllocGvn),
         num_entries_(0u) {
-    // ArenaAllocator returns zeroed memory, so entries of buckets_ and
-    // buckets_owned_ are initialized to null and false, respectively.
     DCHECK(IsPowerOfTwo(num_buckets_));
     PopulateFromInternal(other);
   }
diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc
index 99f9387..a69429f 100644
--- a/runtime/jit/debugger_interface.cc
+++ b/runtime/jit/debugger_interface.cc
@@ -301,7 +301,7 @@
     return;  // Nothing to do.
   }
 
-  std::vector<const uint8_t*> added_elf_files;
+  std::vector<ArrayRef<const uint8_t>> added_elf_files;
   std::vector<const void*> removed_symbols;
   auto added_it = g_jit_debug_entries.begin();
   auto removed_it = removed_entries.begin();
@@ -312,7 +312,8 @@
     auto added_begin = added_it;
     while (added_it != g_jit_debug_entries.end() &&
            AlignDown(added_it->first, kGroupSize) == group_ptr) {
-      added_elf_files.push_back((added_it++)->second->symfile_addr_);
+      JITCodeEntry* entry = (added_it++)->second;
+      added_elf_files.emplace_back(entry->symfile_addr_, entry->symfile_size_);
     }
     removed_symbols.clear();
     while (removed_it != removed_entries.end() &&
diff --git a/runtime/jit/debugger_interface.h b/runtime/jit/debugger_interface.h
index 17beb4b..51b7041 100644
--- a/runtime/jit/debugger_interface.h
+++ b/runtime/jit/debugger_interface.h
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "arch/instruction_set_features.h"
+#include "base/array_ref.h"
 #include "base/locks.h"
 
 namespace art {
@@ -33,7 +34,7 @@
 typedef std::vector<uint8_t> PackElfFileForJITFunction(
     InstructionSet isa,
     const InstructionSetFeatures* features,
-    std::vector<const uint8_t*>& added_elf_files,
+    std::vector<ArrayRef<const uint8_t>>& added_elf_files,
     std::vector<const void*>& removed_symbols,
     /*out*/ size_t* num_symbols);
 
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index 141dd22..3390a99 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -113,12 +113,12 @@
 
   bool HasSuperclass() const { return dex_file_.IsTypeIndexValid(GetSuperclassIndex()); }
 
-  std::string GetSuperclassDescriptor() const {
+  std::string_view GetSuperclassDescriptor() const {
     return HasSuperclass() ? dex_file_.StringByTypeIdx(GetSuperclassIndex()) : "";
   }
 
-  std::set<std::string> GetInterfaceDescriptors() const {
-    std::set<std::string> list;
+  std::set<std::string_view> GetInterfaceDescriptors() const {
+    std::set<std::string_view> list;
     const dex::TypeList* ifaces = dex_file_.GetInterfacesList(GetClassDef());
     for (uint32_t i = 0; ifaces != nullptr && i < ifaces->Size(); ++i) {
       list.insert(dex_file_.StringByTypeIdx(ifaces->GetTypeItem(i).type_idx_));
@@ -131,24 +131,12 @@
 
   inline bool Equals(const DexClass& other) const {
     bool equals = strcmp(GetDescriptor(), other.GetDescriptor()) == 0;
+
     if (equals) {
-      // TODO(dbrazdil): Check that methods/fields match as well once b/111116543 is fixed.
-      CHECK_EQ(GetAccessFlags(), other.GetAccessFlags())
-          << "Inconsistent access flags of class " << GetDescriptor() << ": "
-          << "0x" << std::hex << GetAccessFlags() << std::dec << " (" << dex_file_.GetLocation()
-          << ") and 0x" << std::hex << other.GetAccessFlags() << std::dec << " ("
-          << other.dex_file_.GetLocation() << ")";
-      CHECK_EQ(GetSuperclassDescriptor(), other.GetSuperclassDescriptor())
-          << "Inconsistent superclass of class " << GetDescriptor() << ": "
-          << GetSuperclassDescriptor() << " (" << dex_file_.GetLocation()
-          << ") and " << other.GetSuperclassDescriptor() << " (" << other.dex_file_.GetLocation()
-          << ")";
-      CHECK(GetInterfaceDescriptors() == other.GetInterfaceDescriptors())
-          << "Inconsistent set of interfaces of class " << GetDescriptor() << ": "
-          << JoinStringSet(GetInterfaceDescriptors()) << " (" << dex_file_.GetLocation()
-          << ") and " << JoinStringSet(other.GetInterfaceDescriptors()) << " ("
-          << other.dex_file_.GetLocation() << ")";
+      LOG(FATAL) << "Class duplication: " << GetDescriptor() << " in " << dex_file_.GetLocation()
+          << " and " << other.dex_file_.GetLocation();
     }
+
     return equals;
   }
 
@@ -156,7 +144,7 @@
   uint32_t GetAccessFlags() const { return GetClassDef().access_flags_; }
   bool HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; }
 
-  static std::string JoinStringSet(const std::set<std::string>& s) {
+  static std::string JoinStringSet(const std::set<std::string_view>& s) {
     return "{" + ::android::base::Join(std::vector<std::string>(s.begin(), s.end()), ",") + "}";
   }
 };
@@ -209,7 +197,7 @@
   inline uint32_t GetAccessFlags() const { return item_.GetAccessFlags(); }
   inline uint32_t HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; }
 
-  inline std::string GetName() const {
+  inline std::string_view GetName() const {
     return IsMethod() ? item_.GetDexFile().GetMethodName(GetMethodId())
                       : item_.GetDexFile().GetFieldName(GetFieldId());
   }
@@ -508,7 +496,7 @@
   }
 
  private:
-  HierarchyClass* FindClass(const std::string& descriptor) {
+  HierarchyClass* FindClass(const std::string_view& descriptor) {
     auto it = classes_.find(descriptor);
     if (it == classes_.end()) {
       return nullptr;
@@ -539,7 +527,7 @@
       CHECK(superclass != nullptr);
       klass.AddExtends(*superclass);
 
-      for (const std::string& iface_desc : dex_klass.GetInterfaceDescriptors()) {
+      for (const std::string_view& iface_desc : dex_klass.GetInterfaceDescriptors()) {
         HierarchyClass* iface = FindClass(iface_desc);
         CHECK(iface != nullptr);
         klass.AddExtends(*iface);
@@ -548,7 +536,7 @@
   }
 
   ClassPath& classpath_;
-  std::map<std::string, HierarchyClass> classes_;
+  std::map<std::string_view, HierarchyClass> classes_;
 };
 
 // Builder of dex section containing hiddenapi flags.