Add code_item_accessors-no_art-inl and use it in dexlist, dexdump

Added new helper to prevent inclusion of ART code. Removed accesses to
dex code.

Bug: 63756964
Bug: 70852830
Test: test-art-host-gtest -j40
Test: mm test-art-host-dexdump -j40

Change-Id: Ie0220df464a5cc2b81c0ee3e0483cdf2de003092
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 527a5b9..f64c89a 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -44,6 +44,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "code_item_accessors-no_art-inl.h"
 #include "dex_file-inl.h"
 #include "dex_file_loader.h"
 #include "dex_file_types.h"
@@ -949,14 +950,14 @@
   fprintf(gOutFile, "%06x:", codeOffset + 0x10 + insnIdx * 2);
 
   // Dump (part of) raw bytes.
-  const u2* insns = pCode->insns_;
+  CodeItemInstructionAccessor accessor(pDexFile, pCode);
   for (u4 i = 0; i < 8; i++) {
     if (i < insnWidth) {
       if (i == 7) {
         fprintf(gOutFile, " ... ");
       } else {
         // Print 16-bit value in little-endian order.
-        const u1* bytePtr = (const u1*) &insns[insnIdx + i];
+        const u1* bytePtr = (const u1*) &accessor.Insns()[insnIdx + i];
         fprintf(gOutFile, " %02x%02x", bytePtr[0], bytePtr[1]);
       }
     } else {
@@ -966,7 +967,7 @@
 
   // Dump pseudo-instruction or opcode.
   if (pDecInsn->Opcode() == Instruction::NOP) {
-    const u2 instr = get2LE((const u1*) &insns[insnIdx]);
+    const u2 instr = get2LE((const u1*) &accessor.Insns()[insnIdx]);
     if (instr == Instruction::kPackedSwitchSignature) {
       fprintf(gOutFile, "|%04x: packed-switch-data (%d units)", insnIdx, insnWidth);
     } else if (instr == Instruction::kSparseSwitchSignature) {
@@ -1167,16 +1168,15 @@
           codeOffset, codeOffset, dot.get(), name, signature.ToString().c_str());
 
   // Iterate over all instructions.
-  const u2* insns = pCode->insns_;
-  for (u4 insnIdx = 0; insnIdx < pCode->insns_size_in_code_units_;) {
-    const Instruction* instruction = Instruction::At(&insns[insnIdx]);
+  CodeItemDataAccessor accessor(pDexFile, pCode);
+  for (const DexInstructionPcPair& pair : accessor) {
+    const Instruction* instruction = &pair.Inst();
     const u4 insnWidth = instruction->SizeInCodeUnits();
     if (insnWidth == 0) {
-      fprintf(stderr, "GLITCH: zero-width instruction at idx=0x%04x\n", insnIdx);
+      fprintf(stderr, "GLITCH: zero-width instruction at idx=0x%04x\n", pair.DexPc());
       break;
     }
-    dumpInstruction(pDexFile, pCode, codeOffset, insnIdx, insnWidth, instruction);
-    insnIdx += insnWidth;
+    dumpInstruction(pDexFile, pCode, codeOffset, pair.DexPc(), insnWidth, instruction);
   }  // for
 }
 
@@ -1185,11 +1185,13 @@
  */
 static void dumpCode(const DexFile* pDexFile, u4 idx, u4 flags,
                      const DexFile::CodeItem* pCode, u4 codeOffset) {
-  fprintf(gOutFile, "      registers     : %d\n", pCode->registers_size_);
-  fprintf(gOutFile, "      ins           : %d\n", pCode->ins_size_);
-  fprintf(gOutFile, "      outs          : %d\n", pCode->outs_size_);
+  CodeItemDebugInfoAccessor accessor(pDexFile, pCode, pDexFile->GetDebugInfoOffset(pCode));
+
+  fprintf(gOutFile, "      registers     : %d\n", accessor.RegistersSize());
+  fprintf(gOutFile, "      ins           : %d\n", accessor.InsSize());
+  fprintf(gOutFile, "      outs          : %d\n", accessor.OutsSize());
   fprintf(gOutFile, "      insns size    : %d 16-bit code units\n",
-          pCode->insns_size_in_code_units_);
+          accessor.InsnsSizeInCodeUnits());
 
   // Bytecode disassembly, if requested.
   if (gOptions.disassemble) {
@@ -1202,17 +1204,9 @@
   // Positions and locals table in the debug info.
   bool is_static = (flags & kAccStatic) != 0;
   fprintf(gOutFile, "      positions     : \n");
-  uint32_t debug_info_offset = pDexFile->GetDebugInfoOffset(pCode);
-  pDexFile->DecodeDebugPositionInfo(debug_info_offset, dumpPositionsCb, nullptr);
+  pDexFile->DecodeDebugPositionInfo(accessor.DebugInfoOffset(), dumpPositionsCb, nullptr);
   fprintf(gOutFile, "      locals        : \n");
-  pDexFile->DecodeDebugLocalInfo(pCode->registers_size_,
-                                 pCode->ins_size_,
-                                 pCode->insns_size_in_code_units_,
-                                 debug_info_offset,
-                                 is_static,
-                                 idx,
-                                 dumpLocalsCb,
-                                 nullptr);
+  accessor.DecodeDebugLocalInfo(is_static, idx, dumpLocalsCb, nullptr);
 }
 
 /*
diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc
index 4c13ed6..2c910d4 100644
--- a/dexlist/dexlist.cc
+++ b/dexlist/dexlist.cc
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 
 #include "base/logging.h"  // For InitLogging.
+#include "code_item_accessors-no_art-inl.h"
 #include "dex_file-inl.h"
 #include "dex_file_loader.h"
 #include "mem_map.h"
@@ -99,6 +100,7 @@
   if (pCode == nullptr || codeOffset == 0) {
     return;
   }
+  CodeItemDebugInfoAccessor accessor(pDexFile, pCode, pDexFile->GetDebugInfoOffset(pCode));
 
   // Method information.
   const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
@@ -121,8 +123,7 @@
 
   // Find the first line.
   int firstLine = -1;
-  uint32_t debug_info_offset = pDexFile->GetDebugInfoOffset(pCode);
-  pDexFile->DecodeDebugPositionInfo(debug_info_offset, positionsCb, &firstLine);
+  pDexFile->DecodeDebugPositionInfo(accessor.DebugInfoOffset(), positionsCb, &firstLine);
 
   // Method signature.
   const Signature signature = pDexFile->GetMethodSignature(pMethodId);
@@ -130,7 +131,7 @@
 
   // Dump actual method information.
   fprintf(gOutFile, "0x%08x %d %s %s %s %s %d\n",
-          insnsOff, pCode->insns_size_in_code_units_ * 2,
+          insnsOff, accessor.InsnsSizeInCodeUnits() * 2,
           className.get(), methodName, typeDesc, fileName, firstLine);
 
   free(typeDesc);
diff --git a/runtime/code_item_accessors-inl.h b/runtime/code_item_accessors-inl.h
index 4f4d8cc..1ba3c55 100644
--- a/runtime/code_item_accessors-inl.h
+++ b/runtime/code_item_accessors-inl.h
@@ -17,7 +17,7 @@
 #ifndef ART_RUNTIME_CODE_ITEM_ACCESSORS_INL_H_
 #define ART_RUNTIME_CODE_ITEM_ACCESSORS_INL_H_
 
-#include "code_item_accessors.h"
+#include "code_item_accessors-no_art-inl.h"
 
 #include "art_method-inl.h"
 #include "cdex/compact_dex_file.h"
@@ -27,45 +27,9 @@
 
 namespace art {
 
-inline void CodeItemInstructionAccessor::Init(const CompactDexFile::CodeItem& code_item) {
-  insns_size_in_code_units_ = code_item.insns_size_in_code_units_;
-  insns_ = code_item.insns_;
-}
-
-inline void CodeItemInstructionAccessor::Init(const StandardDexFile::CodeItem& code_item) {
-  insns_size_in_code_units_ = code_item.insns_size_in_code_units_;
-  insns_ = code_item.insns_;
-}
-
-inline void CodeItemInstructionAccessor::Init(const DexFile* dex_file,
-                                              const DexFile::CodeItem* code_item) {
-  DCHECK(dex_file != nullptr);
-  DCHECK(code_item != nullptr);
-  if (dex_file->IsCompactDexFile()) {
-    Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
-  } else {
-    DCHECK(dex_file->IsStandardDexFile());
-    Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
-  }
-}
-
-inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(
-    const DexFile* dex_file,
-    const DexFile::CodeItem* code_item) {
-  Init(dex_file, code_item);
-}
-
 inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(ArtMethod* method)
     : CodeItemInstructionAccessor(method->GetDexFile(), method->GetCodeItem()) {}
 
-inline DexInstructionIterator CodeItemInstructionAccessor::begin() const {
-  return DexInstructionIterator(insns_, 0u);
-}
-
-inline DexInstructionIterator CodeItemInstructionAccessor::end() const {
-  return DexInstructionIterator(insns_, insns_size_in_code_units_);
-}
-
 inline CodeItemInstructionAccessor CodeItemInstructionAccessor::CreateNullable(
     ArtMethod* method) {
   DCHECK(method != nullptr);
@@ -79,78 +43,14 @@
   return ret;
 }
 
-inline void CodeItemDataAccessor::Init(const CompactDexFile::CodeItem& code_item) {
-  CodeItemInstructionAccessor::Init(code_item);
-  registers_size_ = code_item.registers_size_;
-  ins_size_ = code_item.ins_size_;
-  outs_size_ = code_item.outs_size_;
-  tries_size_ = code_item.tries_size_;
-}
-
-inline void CodeItemDataAccessor::Init(const StandardDexFile::CodeItem& code_item) {
-  CodeItemInstructionAccessor::Init(code_item);
-  registers_size_ = code_item.registers_size_;
-  ins_size_ = code_item.ins_size_;
-  outs_size_ = code_item.outs_size_;
-  tries_size_ = code_item.tries_size_;
-}
-
-inline void CodeItemDataAccessor::Init(const DexFile* dex_file,
-                                       const DexFile::CodeItem* code_item) {
-  DCHECK(dex_file != nullptr);
-  DCHECK(code_item != nullptr);
-  if (dex_file->IsCompactDexFile()) {
-    CodeItemDataAccessor::Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
-  } else {
-    DCHECK(dex_file->IsStandardDexFile());
-    CodeItemDataAccessor::Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
-  }
-}
-
-inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile* dex_file,
-                                                  const DexFile::CodeItem* code_item) {
-  Init(dex_file, code_item);
-}
-
 inline CodeItemDataAccessor::CodeItemDataAccessor(ArtMethod* method)
     : CodeItemDataAccessor(method->GetDexFile(), method->GetCodeItem()) {}
 
-inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(
-    const DexFile* dex_file,
-    const DexFile::CodeItem* code_item) {
-  CodeItemDataAccessor ret;
-  if (code_item != nullptr) {
-    ret.Init(dex_file, code_item);
-  } else {
-    DCHECK(!ret.HasCodeItem()) << "Should be null initialized";
-  }
-  return ret;
-}
-
 inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(ArtMethod* method) {
   DCHECK(method != nullptr);
   return CreateNullable(method->GetDexFile(), method->GetCodeItem());
 }
 
-inline IterationRange<const DexFile::TryItem*> CodeItemDataAccessor::TryItems() const {
-  const DexFile::TryItem* try_items = DexFile::GetTryItems(end(), 0u);
-  return {
-    try_items,
-    try_items + TriesSize() };
-}
-
-inline const uint8_t* CodeItemDataAccessor::GetCatchHandlerData(size_t offset) const {
-  return DexFile::GetCatchHandlerData(end(), TriesSize(), offset);
-}
-
-inline const DexFile::TryItem* CodeItemDataAccessor::FindTryItem(uint32_t try_dex_pc) const {
-  IterationRange<const DexFile::TryItem*> try_items(TryItems());
-  int32_t index = DexFile::FindTryItem(try_items.begin(),
-                                       try_items.end() - try_items.begin(),
-                                       try_dex_pc);
-  return index != -1 ? &try_items.begin()[index] : nullptr;
-}
-
 inline CodeItemDebugInfoAccessor::CodeItemDebugInfoAccessor(ArtMethod* method)
     : CodeItemDebugInfoAccessor(method->GetDexFile(), method->GetCodeItem()) {}
 
@@ -159,21 +59,7 @@
   if (code_item == nullptr) {
     return;
   }
-  debug_info_offset_ = OatFile::GetDebugInfoOffset(*dex_file, code_item);
-  if (dex_file->IsCompactDexFile()) {
-    Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
-  } else {
-    DCHECK(dex_file->IsStandardDexFile());
-    Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
-  }
-}
-
-inline void CodeItemDebugInfoAccessor::Init(const CompactDexFile::CodeItem& code_item) {
-  CodeItemDataAccessor::Init(code_item);
-}
-
-inline void CodeItemDebugInfoAccessor::Init(const StandardDexFile::CodeItem& code_item) {
-  CodeItemDataAccessor::Init(code_item);
+  Init(dex_file, code_item, OatFile::GetDebugInfoOffset(*dex_file, code_item));
 }
 
 }  // namespace art
diff --git a/runtime/code_item_accessors-no_art-inl.h b/runtime/code_item_accessors-no_art-inl.h
new file mode 100644
index 0000000..96321b5
--- /dev/null
+++ b/runtime/code_item_accessors-no_art-inl.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ART_RUNTIME_CODE_ITEM_ACCESSORS_NO_ART_INL_H_
+#define ART_RUNTIME_CODE_ITEM_ACCESSORS_NO_ART_INL_H_
+
+#include "code_item_accessors.h"
+
+#include "cdex/compact_dex_file.h"
+#include "dex_file-inl.h"
+#include "standard_dex_file.h"
+
+// The no ART version is used by binaries that don't include the whole runtime.
+
+namespace art {
+
+inline void CodeItemInstructionAccessor::Init(const CompactDexFile::CodeItem& code_item) {
+  insns_size_in_code_units_ = code_item.insns_size_in_code_units_;
+  insns_ = code_item.insns_;
+}
+
+inline void CodeItemInstructionAccessor::Init(const StandardDexFile::CodeItem& code_item) {
+  insns_size_in_code_units_ = code_item.insns_size_in_code_units_;
+  insns_ = code_item.insns_;
+}
+
+inline void CodeItemInstructionAccessor::Init(const DexFile* dex_file,
+                                              const DexFile::CodeItem* code_item) {
+  DCHECK(dex_file != nullptr);
+  DCHECK(code_item != nullptr);
+  if (dex_file->IsCompactDexFile()) {
+    Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
+  } else {
+    DCHECK(dex_file->IsStandardDexFile());
+    Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
+  }
+}
+
+inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(
+    const DexFile* dex_file,
+    const DexFile::CodeItem* code_item) {
+  Init(dex_file, code_item);
+}
+
+inline DexInstructionIterator CodeItemInstructionAccessor::begin() const {
+  return DexInstructionIterator(insns_, 0u);
+}
+
+inline DexInstructionIterator CodeItemInstructionAccessor::end() const {
+  return DexInstructionIterator(insns_, insns_size_in_code_units_);
+}
+
+inline void CodeItemDataAccessor::Init(const CompactDexFile::CodeItem& code_item) {
+  CodeItemInstructionAccessor::Init(code_item);
+  registers_size_ = code_item.registers_size_;
+  ins_size_ = code_item.ins_size_;
+  outs_size_ = code_item.outs_size_;
+  tries_size_ = code_item.tries_size_;
+}
+
+inline void CodeItemDataAccessor::Init(const StandardDexFile::CodeItem& code_item) {
+  CodeItemInstructionAccessor::Init(code_item);
+  registers_size_ = code_item.registers_size_;
+  ins_size_ = code_item.ins_size_;
+  outs_size_ = code_item.outs_size_;
+  tries_size_ = code_item.tries_size_;
+}
+
+inline void CodeItemDataAccessor::Init(const DexFile* dex_file,
+                                       const DexFile::CodeItem* code_item) {
+  DCHECK(dex_file != nullptr);
+  DCHECK(code_item != nullptr);
+  if (dex_file->IsCompactDexFile()) {
+    CodeItemDataAccessor::Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
+  } else {
+    DCHECK(dex_file->IsStandardDexFile());
+    CodeItemDataAccessor::Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
+  }
+}
+
+inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile* dex_file,
+                                                  const DexFile::CodeItem* code_item) {
+  Init(dex_file, code_item);
+}
+
+inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(
+    const DexFile* dex_file,
+    const DexFile::CodeItem* code_item) {
+  CodeItemDataAccessor ret;
+  if (code_item != nullptr) {
+    ret.Init(dex_file, code_item);
+  } else {
+    DCHECK(!ret.HasCodeItem()) << "Should be null initialized";
+  }
+  return ret;
+}
+
+inline IterationRange<const DexFile::TryItem*> CodeItemDataAccessor::TryItems() const {
+  const DexFile::TryItem* try_items = DexFile::GetTryItems(end(), 0u);
+  return {
+    try_items,
+    try_items + TriesSize() };
+}
+
+inline const uint8_t* CodeItemDataAccessor::GetCatchHandlerData(size_t offset) const {
+  return DexFile::GetCatchHandlerData(end(), TriesSize(), offset);
+}
+
+inline const DexFile::TryItem* CodeItemDataAccessor::FindTryItem(uint32_t try_dex_pc) const {
+  IterationRange<const DexFile::TryItem*> try_items(TryItems());
+  int32_t index = DexFile::FindTryItem(try_items.begin(),
+                                       try_items.end() - try_items.begin(),
+                                       try_dex_pc);
+  return index != -1 ? &try_items.begin()[index] : nullptr;
+}
+
+inline void CodeItemDebugInfoAccessor::Init(const DexFile* dex_file,
+                                            const DexFile::CodeItem* code_item,
+                                            uint32_t debug_info_offset) {
+  dex_file_ = dex_file;
+  debug_info_offset_ = debug_info_offset;
+  if (dex_file->IsCompactDexFile()) {
+    Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
+  } else {
+    DCHECK(dex_file->IsStandardDexFile());
+    Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
+  }
+}
+
+inline void CodeItemDebugInfoAccessor::Init(const CompactDexFile::CodeItem& code_item) {
+  CodeItemDataAccessor::Init(code_item);
+}
+
+inline void CodeItemDebugInfoAccessor::Init(const StandardDexFile::CodeItem& code_item) {
+  CodeItemDataAccessor::Init(code_item);
+}
+
+template<typename NewLocalCallback>
+inline bool CodeItemDebugInfoAccessor::DecodeDebugLocalInfo(bool is_static,
+                                                            uint32_t method_idx,
+                                                            NewLocalCallback new_local,
+                                                            void* context) const {
+  return dex_file_->DecodeDebugLocalInfo(RegistersSize(),
+                                         InsSize(),
+                                         InsnsSizeInCodeUnits(),
+                                         DebugInfoOffset(),
+                                         is_static,
+                                         method_idx,
+                                         new_local,
+                                         context);
+}
+
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_CODE_ITEM_ACCESSORS_NO_ART_INL_H_
diff --git a/runtime/code_item_accessors.h b/runtime/code_item_accessors.h
index a089a27..9f40114 100644
--- a/runtime/code_item_accessors.h
+++ b/runtime/code_item_accessors.h
@@ -142,17 +142,35 @@
   ALWAYS_INLINE CodeItemDebugInfoAccessor(const DexFile* dex_file,
                                           const DexFile::CodeItem* code_item);
 
+  // Initialize with an existing offset.
+  ALWAYS_INLINE CodeItemDebugInfoAccessor(const DexFile* dex_file,
+                                          const DexFile::CodeItem* code_item,
+                                          uint32_t debug_info_offset) {
+    Init(dex_file, code_item, debug_info_offset);
+  }
+
+  ALWAYS_INLINE void Init(const DexFile* dex_file,
+                          const DexFile::CodeItem* code_item,
+                          uint32_t debug_info_offset);
+
   ALWAYS_INLINE explicit CodeItemDebugInfoAccessor(ArtMethod* method);
 
   uint32_t DebugInfoOffset() const {
     return debug_info_offset_;
   }
 
+  template<typename NewLocalCallback>
+  bool DecodeDebugLocalInfo(bool is_static,
+                            uint32_t method_idx,
+                            NewLocalCallback new_local,
+                            void* context) const;
+
  protected:
   ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item);
   ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item);
 
  private:
+  const DexFile* dex_file_ = nullptr;
   uint32_t debug_info_offset_ = 0u;
 };