dexdump2: Remove conversion from dollar sign to dot

This was presumably added to render nested classes similar to how they
are referred to in source, but since a dollar sign ('$') is a valid
character in a class name and its use is growing thanks to annotation
processors and D8/R8 it only resulted in very wrong names. If you are
at the level where you can understand dexdump's output, you can handle
dollar signs being present in nested class names.

Before:

    [000234] -..Lambda.Lambda.fcyZxanqBZSHC_nf-noKh-e3bnY.<clinit>:()V
        0000: new-instance v0,
        L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY; // type@0000
        0002: invoke-direct {v0},
        L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY;.<init>:()V // method@0001
        0005: sput-object v0, L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY;.INSTANCE:L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY; // field@0000
        0007: return-void

After:

    [000234] -$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY.<clinit>:()V
        0000: new-instance v0, L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY; // type@0000
        0002: invoke-direct {v0}, L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY;.<init>:()V // method@0001
        0005: sput-object v0, L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY;.INSTANCE:L-$$Lambda$Lambda$fcyZxanqBZSHC_nf-noKh-e3bnY; // field@0000
        0007: return-void

Bug: 113152880
Test: art/test/dexdump/run-all-tests
Test: dalvik/dx/tests/run-all-tests
Change-Id: I22a1d3db5b7e0fe6b6c77b5cf8f37e7254bd40f4
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index f8274e2..e9b6402 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -123,8 +123,7 @@
 /*
  * Converts a type descriptor to human-readable "dotted" form.  For
  * example, "Ljava/lang/String;" becomes "java.lang.String", and
- * "[I" becomes "int[]".  Also converts '$' to '.', which means this
- * form can't be converted back to a descriptor.
+ * "[I" becomes "int[]".
  */
 static std::unique_ptr<char[]> descriptorToDot(const char* str) {
   int targetLen = strlen(str);
@@ -157,7 +156,7 @@
   int i = 0;
   for (; i < targetLen; i++) {
     const char ch = str[offset + i];
-    newStr[i] = (ch == '/' || ch == '$') ? '.' : ch;
+    newStr[i] = (ch == '/') ? '.' : ch;
   }  // for
 
   // Add the appropriate number of brackets for arrays.
@@ -171,10 +170,9 @@
 }
 
 /*
- * Converts the class name portion of a type descriptor to human-readable
- * "dotted" form. For example, "Ljava/lang/String;" becomes "String".
+ * Retrieves the class name portion of a type descriptor.
  */
-static std::unique_ptr<char[]> descriptorClassToDot(const char* str) {
+static std::unique_ptr<char[]> descriptorClassToName(const char* str) {
   // Reduce to just the class name prefix.
   const char* lastSlash = strrchr(str, '/');
   if (lastSlash == nullptr) {
@@ -187,8 +185,7 @@
   const int targetLen = strlen(lastSlash);
   std::unique_ptr<char[]> newStr(new char[targetLen]);
   for (int i = 0; i < targetLen - 1; i++) {
-    const char ch = lastSlash[i];
-    newStr[i] = ch == '$' ? '.' : ch;
+    newStr[i] = lastSlash[i];
   }  // for
   newStr[targetLen - 1] = '\0';
   return newStr;
@@ -1250,7 +1247,7 @@
 
     // Method name and prototype.
     if (constructor) {
-      std::unique_ptr<char[]> dot(descriptorClassToDot(backDescriptor));
+      std::unique_ptr<char[]> dot(descriptorClassToName(backDescriptor));
       fprintf(gOutFile, "<constructor name=\"%s\"\n", dot.get());
       dot = descriptorToDot(backDescriptor);
       fprintf(gOutFile, " type=\"%s\"\n", dot.get());
@@ -1469,7 +1466,7 @@
     }
     fprintf(gOutFile, "  Interfaces        -\n");
   } else {
-    std::unique_ptr<char[]> dot(descriptorClassToDot(classDescriptor));
+    std::unique_ptr<char[]> dot(descriptorClassToName(classDescriptor));
     fprintf(gOutFile, "<class name=\"%s\"\n", dot.get());
     if (superclassDescriptor != nullptr) {
       dot = descriptorToDot(superclassDescriptor);
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index d6dd9d1..bd7a301 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -71,26 +71,10 @@
 }
 
 /*
- * Converts a type descriptor to human-readable "dotted" form.  For
- * example, "Ljava/lang/String;" becomes "java.lang.String", and
- * "[I" becomes "int[]".  Also converts '$' to '.', which means this
- * form can't be converted back to a descriptor.
- */
-static std::string DescriptorToDotWrapper(const char* descriptor) {
-  std::string result = DescriptorToDot(descriptor);
-  size_t found = result.find('$');
-  while (found != std::string::npos) {
-    result[found] = '.';
-    found = result.find('$', found);
-  }
-  return result;
-}
-
-/*
  * Converts the class name portion of a type descriptor to human-readable
  * "dotted" form. For example, "Ljava/lang/String;" becomes "String".
  */
-static std::string DescriptorClassToDot(const char* str) {
+static std::string DescriptorClassToName(const char* str) {
   std::string descriptor(str);
   // Reduce to just the class name prefix.
   size_t last_slash = descriptor.rfind('/');
@@ -104,13 +88,6 @@
   size_t size = descriptor.size() - 1 - last_slash;
   std::string result(descriptor.substr(last_slash, size));
 
-  // Replace '$' with '.'.
-  size_t dollar_sign = result.find('$');
-  while (dollar_sign != std::string::npos) {
-    result[dollar_sign] = '.';
-    dollar_sign = result.find('$', dollar_sign);
-  }
-
   return result;
 }
 
@@ -786,7 +763,7 @@
   if (options_.output_format_ == kOutputPlain) {
     fprintf(out_file_, "    #%d              : '%s'\n", i, interface_name);
   } else {
-    std::string dot(DescriptorToDotWrapper(interface_name));
+    std::string dot(DescriptorToDot(interface_name));
     fprintf(out_file_, "<implements name=\"%s\">\n</implements>\n", dot.c_str());
   }
 }
@@ -1044,7 +1021,7 @@
   const char* back_descriptor = method_id->Class()->GetStringId()->Data();
 
   // Generate header.
-  std::string dot(DescriptorToDotWrapper(back_descriptor));
+  std::string dot(DescriptorToDot(back_descriptor));
   fprintf(out_file_, "%06x:                                        |[%06x] %s.%s:%s\n",
           code_offset, code_offset, dot.c_str(), name, type_descriptor.c_str());
 
@@ -1212,9 +1189,9 @@
 
     // Method name and prototype.
     if (constructor) {
-      std::string dot(DescriptorClassToDot(back_descriptor));
+      std::string dot(DescriptorClassToName(back_descriptor));
       fprintf(out_file_, "<constructor name=\"%s\"\n", dot.c_str());
-      dot = DescriptorToDotWrapper(back_descriptor);
+      dot = DescriptorToDot(back_descriptor);
       fprintf(out_file_, " type=\"%s\"\n", dot.c_str());
     } else {
       fprintf(out_file_, "<method name=\"%s\"\n", name);
@@ -1223,7 +1200,7 @@
         LOG(ERROR) << "bad method type descriptor '" << type_descriptor << "'";
         goto bail;
       }
-      std::string dot(DescriptorToDotWrapper(return_type + 1));
+      std::string dot(DescriptorToDot(return_type + 1));
       fprintf(out_file_, " return=\"%s\"\n", dot.c_str());
       fprintf(out_file_, " abstract=%s\n", QuotedBool((flags & kAccAbstract) != 0));
       fprintf(out_file_, " native=%s\n", QuotedBool((flags & kAccNative) != 0));
@@ -1265,7 +1242,7 @@
       }
       // Null terminate and display.
       *cp++ = '\0';
-      std::string dot(DescriptorToDotWrapper(tmp_buf));
+      std::string dot(DescriptorToDot(tmp_buf));
       fprintf(out_file_, "<parameter name=\"arg%d\" type=\"%s\">\n"
                         "</parameter>\n", arg_num++, dot.c_str());
     }  // while
@@ -1309,7 +1286,7 @@
     }
   } else if (options_.output_format_ == kOutputXml) {
     fprintf(out_file_, "<field name=\"%s\"\n", name);
-    std::string dot(DescriptorToDotWrapper(type_descriptor));
+    std::string dot(DescriptorToDot(type_descriptor));
     fprintf(out_file_, " type=\"%s\"\n", dot.c_str());
     fprintf(out_file_, " transient=%s\n", QuotedBool((flags & kAccTransient) != 0));
     fprintf(out_file_, " volatile=%s\n", QuotedBool((flags & kAccVolatile) != 0));
@@ -1415,10 +1392,10 @@
     }
     fprintf(out_file_, "  Interfaces        -\n");
   } else {
-    std::string dot(DescriptorClassToDot(class_descriptor));
+    std::string dot(DescriptorClassToName(class_descriptor));
     fprintf(out_file_, "<class name=\"%s\"\n", dot.c_str());
     if (superclass_descriptor != nullptr) {
-      dot = DescriptorToDotWrapper(superclass_descriptor);
+      dot = DescriptorToDot(superclass_descriptor);
       fprintf(out_file_, " extends=\"%s\"\n", dot.c_str());
     }
     fprintf(out_file_, " interface=%s\n",
diff --git a/test/dexdump/bytecodes.txt b/test/dexdump/bytecodes.txt
index e1a381e..1ed66e8 100644
--- a/test/dexdump/bytecodes.txt
+++ b/test/dexdump/bytecodes.txt
@@ -176,7 +176,7 @@
       ins           : 1
       outs          : 1
       insns size    : 4 16-bit code units
-0009a8:                                        |[0009a8] com.google.android.test.R.attr.<init>:()V
+0009a8:                                        |[0009a8] com.google.android.test.R$attr.<init>:()V
 0009b8: 7010 1900 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0019
 0009be: 0e00                                   |0003: return-void
       catches       : (none)
@@ -228,7 +228,7 @@
       ins           : 1
       outs          : 1
       insns size    : 4 16-bit code units
-0009c0:                                        |[0009c0] com.google.android.test.R.drawable.<init>:()V
+0009c0:                                        |[0009c0] com.google.android.test.R$drawable.<init>:()V
 0009d0: 7010 1900 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0019
 0009d6: 0e00                                   |0003: return-void
       catches       : (none)
diff --git a/test/dexdump/bytecodes.xml b/test/dexdump/bytecodes.xml
index d08c2e9..d4ee3a7 100755
--- a/test/dexdump/bytecodes.xml
+++ b/test/dexdump/bytecodes.xml
@@ -71,7 +71,7 @@
 >
 </constructor>
 </class>
-<class name="R.attr"
+<class name="R$attr"
  extends="java.lang.Object"
  interface="false"
  abstract="false"
@@ -79,15 +79,15 @@
  final="true"
  visibility="public"
 >
-<constructor name="R.attr"
- type="com.google.android.test.R.attr"
+<constructor name="R$attr"
+ type="com.google.android.test.R$attr"
  static="false"
  final="false"
  visibility="public"
 >
 </constructor>
 </class>
-<class name="R.drawable"
+<class name="R$drawable"
  extends="java.lang.Object"
  interface="false"
  abstract="false"
@@ -105,8 +105,8 @@
  value="2130837504"
 >
 </field>
-<constructor name="R.drawable"
- type="com.google.android.test.R.drawable"
+<constructor name="R$drawable"
+ type="com.google.android.test.R$drawable"
  static="false"
  final="false"
  visibility="public"
diff --git a/test/dexdump/checkers.xml b/test/dexdump/checkers.xml
index 4e56ea2..3d3bac2 100755
--- a/test/dexdump/checkers.xml
+++ b/test/dexdump/checkers.xml
@@ -181,7 +181,7 @@
  final="true"
  visibility="public"
 >
-<parameter name="arg0" type="android.content.SharedPreferences.Editor">
+<parameter name="arg0" type="android.content.SharedPreferences$Editor">
 </parameter>
 </method>
 <method name="a"
diff --git a/test/dexdump/invoke-custom.txt b/test/dexdump/invoke-custom.txt
index cfab248..1bfa053 100644
--- a/test/dexdump/invoke-custom.txt
+++ b/test/dexdump/invoke-custom.txt
@@ -58,7 +58,7 @@
       ins           : 2
       outs          : 2
       insns size    : 4 16-bit code units
-001b18:                                        |[001b18] TestBadBootstrapArguments.TestersConstantCallSite.<init>:(Ljava/lang/invoke/MethodHandle;)V
+001b18:                                        |[001b18] TestBadBootstrapArguments$TestersConstantCallSite.<init>:(Ljava/lang/invoke/MethodHandle;)V
 001b28: 7020 d200 1000                         |0000: invoke-direct {v0, v1}, Ljava/lang/invoke/ConstantCallSite;.<init>:(Ljava/lang/invoke/MethodHandle;)V // method@00d2
 001b2e: 0e00                                   |0003: return-void
       catches       : (none)
@@ -537,7 +537,7 @@
       ins           : 2
       outs          : 1
       insns size    : 4 16-bit code units
-002abc:                                        |[002abc] TestInvocationKinds.Widget.<init>:(I)V
+002abc:                                        |[002abc] TestInvocationKinds$Widget.<init>:(I)V
 002acc: 7010 bf00 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@00bf
 002ad2: 0e00                                   |0003: return-void
       catches       : (none)
@@ -586,7 +586,7 @@
       ins           : 1
       outs          : 1
       insns size    : 4 16-bit code units
-002ee8:                                        |[002ee8] TestInvokeCustomWithConcurrentThreads.1.<init>:()V
+002ee8:                                        |[002ee8] TestInvokeCustomWithConcurrentThreads$1.<init>:()V
 002ef8: 7010 cf00 0000                         |0000: invoke-direct {v0}, Ljava/lang/ThreadLocal;.<init>:()V // method@00cf
 002efe: 0e00                                   |0003: return-void
       catches       : (none)
@@ -605,7 +605,7 @@
       ins           : 1
       outs          : 1
       insns size    : 13 16-bit code units
-002ea0:                                        |[002ea0] TestInvokeCustomWithConcurrentThreads.1.initialValue:()Ljava/lang/Integer;
+002ea0:                                        |[002ea0] TestInvokeCustomWithConcurrentThreads$1.initialValue:()Ljava/lang/Integer;
 002eb0: 7100 6500 0000                         |0000: invoke-static {}, LTestInvokeCustomWithConcurrentThreads;.access$000:()Ljava/util/concurrent/atomic/AtomicInteger; // method@0065
 002eb6: 0c00                                   |0003: move-result-object v0
 002eb8: 6e10 f100 0000                         |0004: invoke-virtual {v0}, Ljava/util/concurrent/atomic/AtomicInteger;.getAndIncrement:()I // method@00f1
@@ -628,7 +628,7 @@
       ins           : 1
       outs          : 1
       insns size    : 5 16-bit code units
-002ecc:                                        |[002ecc] TestInvokeCustomWithConcurrentThreads.1.initialValue:()Ljava/lang/Object;
+002ecc:                                        |[002ecc] TestInvokeCustomWithConcurrentThreads$1.initialValue:()Ljava/lang/Object;
 002edc: 6e10 6100 0100                         |0000: invoke-virtual {v1}, LTestInvokeCustomWithConcurrentThreads$1;.initialValue:()Ljava/lang/Integer; // method@0061
 002ee2: 0c00                                   |0003: move-result-object v0
 002ee4: 1100                                   |0004: return-object v0