Migrated dexlist from Dalvik (libdex) into Art (libart)

Rationale:
The new dexlist (temporarily called dexlist2 until we are
satisfied with the migration) is a re-implementation of the
original dexlist utility that was based on Dalvik functions
in libdex into a new dexlist that is now based on Art functions
in libart instead.

Bug: 22322814
Change-Id: I0f034d66c1a1f3c5450423f57fcdc23e2f5a1e29
diff --git a/Android.mk b/Android.mk
index a050c58..ff39d53 100644
--- a/Android.mk
+++ b/Android.mk
@@ -79,6 +79,7 @@
 include $(art_path)/runtime/Android.mk
 include $(art_path)/compiler/Android.mk
 include $(art_path)/dexdump/Android.mk
+include $(art_path)/dexlist/Android.mk
 include $(art_path)/dex2oat/Android.mk
 include $(art_path)/disassembler/Android.mk
 include $(art_path)/oatdump/Android.mk
@@ -237,9 +238,9 @@
 	$(hide) $(call ART_TEST_PREREQ_FINISHED,$@)
 endif
 
-# Dexdump regression test.
+# Dexdump/list regression test.
 .PHONY: test-art-host-dexdump
-test-art-host-dexdump: dexdump2
+test-art-host-dexdump: dexdump2 dexlist2
 	art/test/dexdump/run-all-tests
 
 # Valgrind. Currently only 32b gtests.
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 273ae0e..0958c64 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -104,6 +104,17 @@
   $(TARGET_CORE_IMAGE_default_no-pic_32) \
   dexdump2
 
+# The dexlist test requires an image and the dexlist utility.
+# TODO: rename into dexlist when migration completes
+ART_GTEST_dexlist_test_HOST_DEPS := \
+  $(HOST_CORE_IMAGE_default_no-pic_64) \
+  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_OUT_EXECUTABLES)/dexlist2
+ART_GTEST_dexlist_test_TARGET_DEPS := \
+  $(TARGET_CORE_IMAGE_default_no-pic_64) \
+  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  dexlist2
+
 # The imgdiag test has dependencies on core.oat since it needs to load it during the test.
 # For the host, also add the installed tool (in the base size, that should suffice). For the
 # target, just the module is fine, the sync will happen late enough.
@@ -132,6 +143,7 @@
 RUNTIME_GTEST_COMMON_SRC_FILES := \
   cmdline/cmdline_parser_test.cc \
   dexdump/dexdump_test.cc \
+  dexlist/dexlist_test.cc \
   imgdiag/imgdiag_test.cc \
   oatdump/oatdump_test.cc \
   runtime/arch/arch_test.cc \
diff --git a/dexlist/Android.mk b/dexlist/Android.mk
new file mode 100755
index 0000000..988fe03
--- /dev/null
+++ b/dexlist/Android.mk
@@ -0,0 +1,54 @@
+# Copyright (C) 2015 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.
+
+# TODO(ajcbik): Art-i-fy this makefile
+
+# TODO(ajcbik): rename dexlist2 into dexlist when Dalvik version is removed
+
+LOCAL_PATH:= $(call my-dir)
+
+dexlist_src_files := dexlist.cc
+dexlist_c_includes := art/runtime
+dexlist_libraries := libart
+
+##
+## Build the device command line tool dexlist.
+##
+
+ifneq ($(SDK_ONLY),true)  # SDK_only doesn't need device version
+include $(CLEAR_VARS)
+LOCAL_CPP_EXTENSION := cc
+LOCAL_SRC_FILES := $(dexlist_src_files)
+LOCAL_C_INCLUDES := $(dexlist_c_includes)
+LOCAL_CFLAGS += -Wall
+LOCAL_SHARED_LIBRARIES += $(dexlist_libraries)
+LOCAL_MODULE := dexlist2
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+include $(BUILD_EXECUTABLE)
+endif # !SDK_ONLY
+
+##
+## Build the host command line tool dexlist.
+##
+
+include $(CLEAR_VARS)
+LOCAL_CPP_EXTENSION := cc
+LOCAL_SRC_FILES := $(dexlist_src_files)
+LOCAL_C_INCLUDES := $(dexlist_c_includes)
+LOCAL_CFLAGS += -Wall
+LOCAL_SHARED_LIBRARIES += $(dexlist_libraries)
+LOCAL_MODULE := dexlist2
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc
new file mode 100644
index 0000000..d7c0e4c
--- /dev/null
+++ b/dexlist/dexlist.cc
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2015 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 dexlist utility.
+ *
+ * This is a re-implementation of the original dexlist utility that was
+ * based on Dalvik functions in libdex into a new dexlist that is now
+ * based on Art functions in libart instead. The output is identical to
+ * the original for correct DEX files. Error messages may differ, however.
+ *
+ * List all methods in all concrete classes in one or more DEX files.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "dex_file-inl.h"
+#include "mem_map.h"
+#include "runtime.h"
+
+namespace art {
+
+static const char* gProgName = "dexlist";
+
+/* Command-line options. */
+static struct {
+  char* argCopy;
+  const char* classToFind;
+  const char* methodToFind;
+  const char* outputFileName;
+} gOptions;
+
+/*
+ * Output file. Defaults to stdout.
+ */
+static FILE* gOutFile = stdout;
+
+/*
+ * Data types that match the definitions in the VM specification.
+ */
+typedef uint8_t  u1;
+typedef uint16_t u2;
+typedef uint32_t u4;
+typedef uint64_t u8;
+typedef int32_t  s4;
+typedef int64_t  s8;
+
+/*
+ * Returns a newly-allocated string for the "dot version" of the class
+ * name for the given type descriptor. That is, The initial "L" and
+ * final ";" (if any) have been removed and all occurrences of '/'
+ * have been changed to '.'.
+ */
+static char* descriptorToDot(const char* str) {
+  size_t at = strlen(str);
+  if (str[0] == 'L') {
+    at -= 2;  // Two fewer chars to copy.
+    str++;
+  }
+  char* newStr = reinterpret_cast<char*>(malloc(at + 1));
+  newStr[at] = '\0';
+  while (at > 0) {
+    at--;
+    newStr[at] = (str[at] == '/') ? '.' : str[at];
+  }
+  return newStr;
+}
+
+/*
+ * Positions table callback; we just want to catch the number of the
+ * first line in the method, which *should* correspond to the first
+ * entry from the table.  (Could also use "min" here.)
+ */
+static bool positionsCb(void* context, u4 /*address*/, u4 lineNum) {
+  int* pFirstLine = reinterpret_cast<int *>(context);
+  if (*pFirstLine == -1) {
+    *pFirstLine = lineNum;
+  }
+  return 0;
+}
+
+/*
+ * Dumps a method.
+ */
+static void dumpMethod(const DexFile* pDexFile,
+                       const char* fileName, u4 idx, u4 flags,
+                       const DexFile::CodeItem* pCode, u4 codeOffset) {
+  // Abstract and native methods don't get listed.
+  if (pCode == nullptr || codeOffset == 0) {
+    return;
+  }
+
+  // Method information.
+  const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
+  const char* methodName = pDexFile->StringDataByIdx(pMethodId.name_idx_);
+  const char* classDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
+  char* className = descriptorToDot(classDescriptor);
+  const u4 insnsOff = codeOffset + 0x10;
+
+  // Don't list methods that do not match a particular query.
+  if (gOptions.methodToFind != nullptr &&
+      (strcmp(gOptions.classToFind, className) != 0 ||
+       strcmp(gOptions.methodToFind, methodName) != 0)) {
+    free(className);
+    return;
+  }
+
+  // If the filename is empty, then set it to something printable.
+  if (fileName == nullptr || fileName[0] == 0) {
+    fileName = "(none)";
+  }
+
+  // Find the first line.
+  int firstLine = -1;
+  bool is_static = (flags & kAccStatic) != 0;
+  pDexFile->DecodeDebugInfo(
+     pCode, is_static, idx, positionsCb, nullptr, &firstLine);
+
+  // Method signature.
+  const Signature signature = pDexFile->GetMethodSignature(pMethodId);
+  char* typeDesc = strdup(signature.ToString().c_str());
+
+  // Dump actual method information.
+  fprintf(gOutFile, "0x%08x %d %s %s %s %s %d\n",
+          insnsOff, pCode->insns_size_in_code_units_ * 2,
+          className, methodName, typeDesc, fileName, firstLine);
+
+  free(typeDesc);
+  free(className);
+}
+
+/*
+ * Runs through all direct and virtual methods in the class.
+ */
+void dumpClass(const DexFile* pDexFile, u4 idx) {
+  const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
+
+  const char* fileName;
+  if (pClassDef.source_file_idx_ == DexFile::kDexNoIndex) {
+    fileName = nullptr;
+  } else {
+    fileName = pDexFile->StringDataByIdx(pClassDef.source_file_idx_);
+  }
+
+  const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
+  if (pEncodedData != nullptr) {
+    ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
+    // Skip the fields.
+    for (; pClassData.HasNextStaticField(); pClassData.Next()) {}
+    for (; pClassData.HasNextInstanceField(); pClassData.Next()) {}
+    // Direct methods.
+    for (; pClassData.HasNextDirectMethod(); pClassData.Next()) {
+      dumpMethod(pDexFile, fileName,
+                 pClassData.GetMemberIndex(),
+                 pClassData.GetRawMemberAccessFlags(),
+                 pClassData.GetMethodCodeItem(),
+                 pClassData.GetMethodCodeItemOffset());
+    }
+    // Virtual methods.
+    for (; pClassData.HasNextVirtualMethod(); pClassData.Next()) {
+      dumpMethod(pDexFile, fileName,
+                 pClassData.GetMemberIndex(),
+                 pClassData.GetRawMemberAccessFlags(),
+                 pClassData.GetMethodCodeItem(),
+                 pClassData.GetMethodCodeItemOffset());
+    }
+  }
+}
+
+/*
+ * Processes a single file (either direct .dex or indirect .zip/.jar/.apk).
+ */
+static int processFile(const char* fileName) {
+  // If the file is not a .dex file, the function tries .zip/.jar/.apk files,
+  // all of which are Zip archives with "classes.dex" inside.
+  std::string error_msg;
+  std::vector<std::unique_ptr<const DexFile>> dex_files;
+  if (!DexFile::Open(fileName, fileName, &error_msg, &dex_files)) {
+    fputs(error_msg.c_str(), stderr);
+    fputc('\n', stderr);
+    return -1;
+  }
+
+  // Determine if opening file yielded a single dex file.
+  //
+  // TODO(ajcbik): this restriction is not really needed, but kept
+  //               for now to stay close to original dexlist; we can
+  //               later relax this!
+  //
+  if (dex_files.size() != 1) {
+    fprintf(stderr, "ERROR: DEX parse failed\n");
+    return -1;
+  }
+  const DexFile* pDexFile = dex_files[0].get();
+
+  // Success. Iterate over all classes.
+  fprintf(gOutFile, "#%s\n", fileName);
+  const u4 classDefsSize = pDexFile->GetHeader().class_defs_size_;
+  for (u4 idx = 0; idx < classDefsSize; idx++) {
+    dumpClass(pDexFile, idx);
+  }
+  return 0;
+}
+
+/*
+ * Shows usage.
+ */
+static void usage(void) {
+  fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
+  fprintf(stderr, "%s: [-m p.c.m] [-o outfile] dexfile...\n", gProgName);
+  fprintf(stderr, "\n");
+}
+
+/*
+ * Main driver of the dexlist utility.
+ */
+int dexlistDriver(int argc, char** argv) {
+  // Art specific set up.
+  InitLogging(argv);
+  MemMap::Init();
+
+  // Reset options.
+  bool wantUsage = false;
+  memset(&gOptions, 0, sizeof(gOptions));
+
+  // Parse all arguments.
+  while (1) {
+    const int ic = getopt(argc, argv, "o:m:");
+    if (ic < 0) {
+      break;  // done
+    }
+    switch (ic) {
+      case 'o':  // output file
+        gOptions.outputFileName = optarg;
+        break;
+      case 'm':
+        // If -m X.Y.Z is given, then find all instances of the
+        // fully-qualified method name. This isn't really what
+        // dexlist is for, but it's easy to do it here.
+        {
+          gOptions.argCopy = strdup(optarg);
+          char* meth = strrchr(gOptions.argCopy, '.');
+          if (meth == nullptr) {
+            fprintf(stderr, "Expected: package.Class.method\n");
+            wantUsage = true;
+          } else {
+            *meth = '\0';
+            gOptions.classToFind = gOptions.argCopy;
+            gOptions.methodToFind = meth + 1;
+          }
+        }
+        break;
+      default:
+        wantUsage = true;
+        break;
+    }  // switch
+  }  // while
+
+  // Detect early problems.
+  if (optind == argc) {
+    fprintf(stderr, "%s: no file specified\n", gProgName);
+    wantUsage = true;
+  }
+  if (wantUsage) {
+    usage();
+    free(gOptions.argCopy);
+    return 2;
+  }
+
+  // Open alternative output file.
+  if (gOptions.outputFileName) {
+    gOutFile = fopen(gOptions.outputFileName, "w");
+    if (!gOutFile) {
+      fprintf(stderr, "Can't open %s\n", gOptions.outputFileName);
+      free(gOptions.argCopy);
+      return 1;
+    }
+  }
+
+  // Process all files supplied on command line. If one of them fails we
+  // continue on, only returning a failure at the end.
+  int result = 0;
+  while (optind < argc) {
+    result |= processFile(argv[optind++]);
+  }  // while
+
+  free(gOptions.argCopy);
+  return result != 0;
+}
+
+}  // namespace art
+
+int main(int argc, char** argv) {
+  return art::dexlistDriver(argc, argv);
+}
+
diff --git a/dexlist/dexlist_test.cc b/dexlist/dexlist_test.cc
new file mode 100644
index 0000000..7b1b63d
--- /dev/null
+++ b/dexlist/dexlist_test.cc
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/stringprintf.h"
+#include "common_runtime_test.h"
+#include "runtime/arch/instruction_set.h"
+#include "runtime/gc/heap.h"
+#include "runtime/gc/space/image_space.h"
+#include "runtime/os.h"
+#include "runtime/utils.h"
+#include "utils.h"
+
+namespace art {
+
+class DexListTest : public CommonRuntimeTest {
+ protected:
+  virtual void SetUp() {
+    CommonRuntimeTest::SetUp();
+    // Dogfood our own lib core dex file.
+    dex_file_ = GetLibCoreDexFileName();
+  }
+
+  // Runs test with given arguments.
+  bool Exec(const std::vector<std::string>& args, std::string* error_msg) {
+    // TODO(ajcbik): dexlist2 -> dexlist
+    std::string file_path = GetTestAndroidRoot();
+    if (IsHost()) {
+      file_path += "/bin/dexlist2";
+    } else {
+      file_path += "/xbin/dexlist2";
+    }
+    EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
+    std::vector<std::string> exec_argv = { file_path };
+    exec_argv.insert(exec_argv.end(), args.begin(), args.end());
+    return ::art::Exec(exec_argv, error_msg);
+  }
+
+  std::string dex_file_;
+};
+
+
+TEST_F(DexListTest, NoInputFileGiven) {
+  std::string error_msg;
+  ASSERT_FALSE(Exec({}, &error_msg)) << error_msg;
+}
+
+TEST_F(DexListTest, CantOpenOutput) {
+  std::string error_msg;
+  ASSERT_FALSE(Exec({"-o", "/joho", dex_file_}, &error_msg)) << error_msg;
+}
+
+TEST_F(DexListTest, IllFormedMethod) {
+  std::string error_msg;
+  ASSERT_FALSE(Exec({"-m", "joho", dex_file_}, &error_msg)) << error_msg;
+}
+
+TEST_F(DexListTest, FullOutput) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec({"-o", "/dev/null", dex_file_}, &error_msg)) << error_msg;
+}
+
+TEST_F(DexListTest, MethodOutput) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec({"-o", "/dev/null", "-m", "java.lang.Object.toString",
+    dex_file_}, &error_msg)) << error_msg;
+}
+
+}  // namespace art
diff --git a/test/dexdump/bytecodes.lst b/test/dexdump/bytecodes.lst
new file mode 100644
index 0000000..aeda7b4
--- /dev/null
+++ b/test/dexdump/bytecodes.lst
@@ -0,0 +1,20 @@
+#bytecodes.dex
+0x000009a0 8 com.google.android.test.BuildConfig <init> ()V BuildConfig.java 4
+0x000009b8 8 com.google.android.test.R$attr <init> ()V R.java 11
+0x000009d0 8 com.google.android.test.R$drawable <init> ()V R.java 13
+0x000009e8 8 com.google.android.test.R <init> ()V R.java 10
+0x00000a00 148 com.google.android.test.Test <clinit> ()V Test.java 7
+0x00000aa4 468 com.google.android.test.Test <init> ()V Test.java 43
+0x00000ca4 478 com.google.android.test.Test add (Ljava/lang/Object;)Ljava/lang/Object; Test.java 179
+0x00000ea0 236 com.google.android.test.Test adds (Ljava/lang/Object;)Ljava/lang/Object; Test.java 201
+0x00000f9c 342 com.google.android.test.Test copies ()V Test.java 216
+0x00001104 156 com.google.android.test.Test doit (I)V Test.java 98
+0x000011b0 146 com.google.android.test.Test geta ()Z Test.java 72
+0x00001254 38 com.google.android.test.Test p (I)V Test.java 120
+0x0000128c 636 com.google.android.test.Test params (BCSIJFDLjava/lang/Object;[I)J Test.java 232
+0x00001518 170 com.google.android.test.Test q (II)V Test.java 127
+0x000015d4 186 com.google.android.test.Test r (II)I Test.java 139
+0x000016a0 388 com.google.android.test.Test s (JJ)J Test.java 159
+0x00001834 96 com.google.android.test.Test seta ()V Test.java 60
+0x000018a4 14 com.google.android.test.Test onStart ()V Test.java 86
+0x000018c4 18 com.google.android.test.Test run ()V Test.java 92
diff --git a/test/dexdump/checkers.lst b/test/dexdump/checkers.lst
new file mode 100644
index 0000000..daef138
--- /dev/null
+++ b/test/dexdump/checkers.lst
@@ -0,0 +1,82 @@
+#checkers.dex
+0x0000149c 8 com.google.android.checkers.Checkers <init> ()V (none) -1
+0x000014b4 66 com.google.android.checkers.Checkers a (Z)V (none) -1
+0x00001508 8 com.google.android.checkers.Checkers onConfigurationChanged (Landroid/content/res/Configuration;)V (none) -1
+0x00001520 118 com.google.android.checkers.Checkers onCreate (Landroid/os/Bundle;)V (none) -1
+0x000015a8 432 com.google.android.checkers.Checkers onCreateOptionsMenu (Landroid/view/Menu;)Z (none) -1
+0x00001768 116 com.google.android.checkers.Checkers onKeyDown (ILandroid/view/KeyEvent;)Z (none) -1
+0x000017ec 316 com.google.android.checkers.Checkers onOptionsItemSelected (Landroid/view/MenuItem;)Z (none) -1
+0x00001938 42 com.google.android.checkers.Checkers onPause ()V (none) -1
+0x00001974 16 com.google.android.checkers.Checkers onStop ()V (none) -1
+0x00001994 88 com.google.android.checkers.Checkers onTrackballEvent (Landroid/view/MotionEvent;)Z (none) -1
+0x000019fc 1324 com.google.android.checkers.CheckersView <init> (Landroid/content/Context;Landroid/content/SharedPreferences;)V (none) -1
+0x00001f48 62 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences$Editor;Ljava/lang/String;[I)V (none) -1
+0x00001f98 66 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences;Ljava/lang/String;[I)V (none) -1
+0x00001fec 126 com.google.android.checkers.CheckersView a (Landroid/graphics/Canvas;IIII)V (none) -1
+0x0000207c 162 com.google.android.checkers.CheckersView a (Landroid/graphics/Canvas;IIIILandroid/graphics/Paint;Landroid/graphics/Paint;Z)V (none) -1
+0x00002130 8 com.google.android.checkers.CheckersView a (Lcom/google/android/checkers/CheckersView;I)V (none) -1
+0x00002148 588 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences;)Z (none) -1
+0x000023d0 22 com.google.android.checkers.CheckersView a (Lcom/google/android/checkers/CheckersView;)Z (none) -1
+0x000023f8 1290 com.google.android.checkers.CheckersView a (ZIIII)Z (none) -1
+0x00002930 204 com.google.android.checkers.CheckersView b (FF)I (none) -1
+0x00002a20 36 com.google.android.checkers.CheckersView b (I)V (none) -1
+0x00002a60 198 com.google.android.checkers.CheckersView b (Landroid/graphics/Canvas;IIII)V (none) -1
+0x00002b38 524 com.google.android.checkers.CheckersView c (I)V (none) -1
+0x00002d54 176 com.google.android.checkers.CheckersView d ()V (none) -1
+0x00002e14 20 com.google.android.checkers.CheckersView e ()Z (none) -1
+0x00002e38 128 com.google.android.checkers.CheckersView a ()V (none) -1
+0x00002ec8 226 com.google.android.checkers.CheckersView a (FF)V (none) -1
+0x00002fd8 32 com.google.android.checkers.CheckersView a (IIII)V (none) -1
+0x00003008 340 com.google.android.checkers.CheckersView a (Landroid/content/SharedPreferences$Editor;)V (none) -1
+0x00003178 34 com.google.android.checkers.CheckersView a (I)Z (none) -1
+0x000031ac 44 com.google.android.checkers.CheckersView a (Z)Z (none) -1
+0x000031f4 60 com.google.android.checkers.CheckersView b ()V (none) -1
+0x0000324c 138 com.google.android.checkers.CheckersView b (Z)Z (none) -1
+0x000032f4 16 com.google.android.checkers.CheckersView c ()I (none) -1
+0x00003320 68 com.google.android.checkers.CheckersView c (Z)Z (none) -1
+0x00003380 38 com.google.android.checkers.CheckersView d (Z)Z (none) -1
+0x000033c4 2528 com.google.android.checkers.CheckersView draw (Landroid/graphics/Canvas;)V (none) -1
+0x00003dd0 38 com.google.android.checkers.CheckersView e (Z)Z (none) -1
+0x00003e14 104 com.google.android.checkers.CheckersView onSizeChanged (IIII)V (none) -1
+0x00003e98 82 com.google.android.checkers.CheckersView onTouchEvent (Landroid/view/MotionEvent;)Z (none) -1
+0x00003efc 128 com.google.android.checkers.CheckersView setLevel (I)V (none) -1
+0x00003f98 2780 com.google.android.checkers.a <clinit> ()V (none) -1
+0x00004a84 188 com.google.android.checkers.a <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x00004b5c 28 com.google.android.checkers.a a (II)I (none) -1
+0x00004b88 2592 com.google.android.checkers.a a (IIIIIZ)I (none) -1
+0x000055b8 110 com.google.android.checkers.a a (IZ)I (none) -1
+0x00005638 196 com.google.android.checkers.a a (Z)I (none) -1
+0x0000570c 112 com.google.android.checkers.a a (ZII)I (none) -1
+0x0000578c 88 com.google.android.checkers.a a (ZIIIZ)I (none) -1
+0x000057f4 68 com.google.android.checkers.a a (ZIIZ)I (none) -1
+0x00005848 152 com.google.android.checkers.a a (IIII)V (none) -1
+0x000058f0 78 com.google.android.checkers.a a (IIIII)V (none) -1
+0x00005950 198 com.google.android.checkers.a a (IIIIIIII)V (none) -1
+0x00005a28 1750 com.google.android.checkers.a a (IZI)Z (none) -1
+0x00006110 92 com.google.android.checkers.a b (ZIIIZ)I (none) -1
+0x0000617c 112 com.google.android.checkers.a b (ZIIZ)I (none) -1
+0x000061fc 38 com.google.android.checkers.a b ()V (none) -1
+0x0000624c 736 com.google.android.checkers.a b (I)V (none) -1
+0x0000653c 198 com.google.android.checkers.a b (IIIIIIII)V (none) -1
+0x00006614 922 com.google.android.checkers.a b (IZI)Z (none) -1
+0x000069c0 108 com.google.android.checkers.a c (ZIIZ)I (none) -1
+0x00006a3c 16 com.google.android.checkers.a c ()V (none) -1
+0x00006a68 406 com.google.android.checkers.a c (IIIIIIII)V (none) -1
+0x00006c10 112 com.google.android.checkers.a d (ZIIZ)I (none) -1
+0x00006c90 16 com.google.android.checkers.a a (ZZ)I (none) -1
+0x00006cb0 90 com.google.android.checkers.a a ()V (none) -1
+0x00006d1c 8 com.google.android.checkers.a a (I)V (none) -1
+0x00006d34 74 com.google.android.checkers.a a (IIIIZ)V (none) -1
+0x00006d90 32 com.google.android.checkers.a b (ZZ)V (none) -1
+0x00006dcc 1052 com.google.android.checkers.a run ()V (none) -1
+0x000071f8 12 com.google.android.checkers.b <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x00007214 28 com.google.android.checkers.b onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x00007240 12 com.google.android.checkers.c <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x0000725c 2 com.google.android.checkers.c onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x00007270 12 com.google.android.checkers.d <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x0000728c 2 com.google.android.checkers.d onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x000072a0 12 com.google.android.checkers.e <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x000072bc 14 com.google.android.checkers.e onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x000072dc 12 com.google.android.checkers.f <init> (Lcom/google/android/checkers/CheckersView;)V (none) -1
+0x000072f8 12 com.google.android.checkers.f onClick (Landroid/content/DialogInterface;I)V (none) -1
+0x00007314 58 com.google.android.checkers.g a ([B)Z (none) -1
diff --git a/test/dexdump/run-all-tests b/test/dexdump/run-all-tests
index f5d8cd6..d9f1e96 100755
--- a/test/dexdump/run-all-tests
+++ b/test/dexdump/run-all-tests
@@ -37,10 +37,14 @@
 tmpdir=/tmp/test-$$
 mkdir ${tmpdir}
 
-# Set up binary and flags to test.
+# Set up dexdump binary and flags to test.
 DEXD="${ANDROID_HOST_OUT}/bin/dexdump2"
-FLAGS1="-dfh"
-FLAGS2="-l xml"
+DEXDFLAGS1="-dfh"
+DEXDFLAGS2="-l xml"
+
+# Set up dexlist binary and flags to test.
+DEXL="${ANDROID_HOST_OUT}/bin/dexlist2"
+DEXLFLAGS=""
 
 # Run the tests.
 passed=0
@@ -50,18 +54,28 @@
     basenm=`basename "${i}" .dex`
     txtfile=${basenm}.txt
     xmlfile=${basenm}.xml
-    genfile1=${tmpdir}/${txtfile}
-    genfile2=${tmpdir}/${xmlfile}
-    ${DEXD} ${FLAGS1} ${i} > ${genfile1}
-    cmp ${txtfile} ${genfile1}
+    lstfile=${basenm}.lst
+    gentxtfile=${tmpdir}/${txtfile}
+    genxmlfile=${tmpdir}/${xmlfile}
+    genlstfile=${tmpdir}/${lstfile}
+    ${DEXD} ${DEXDFLAGS1} ${i} > ${gentxtfile}
+    cmp ${txtfile} ${gentxtfile}
     if [ "$?" = "0" ]; then
         ((passed += 1))
     else
         ((failed += 1))
         echo failed: ${i}
     fi
-    ${DEXD} ${FLAGS2} ${i} > ${genfile2}
-    cmp ${xmlfile} ${genfile2}
+    ${DEXD} ${DEXDFLAGS2} ${i} > ${genxmlfile}
+    cmp ${xmlfile} ${genxmlfile}
+    if [ "$?" = "0" ]; then
+        ((passed += 1))
+    else
+        ((failed += 1))
+        echo failed: ${i}
+    fi
+    ${DEXL} ${DEXLFLAGS} ${i} > ${genlstfile}
+    cmp ${lstfile} ${genlstfile}
     if [ "$?" = "0" ]; then
         ((passed += 1))
     else
@@ -77,7 +91,7 @@
 echo
 
 # Clean up, cd back to original dir.
-#rm -rf ${tmpdir}
+rm -rf ${tmpdir}
 cd ${oldwd}
 
 # Return status.