private static void validateEncode0(
      byte[] info,
      int codeSize,
      int countRegisters,
      boolean isStatic,
      CstMethodRef ref,
      DexFile file,
      PositionList pl,
      LocalList ll) {
    DebugInfoDecoder decoder =
        new DebugInfoDecoder(info, codeSize, countRegisters, isStatic, ref, file);

    decoder.decode();

    /*
     * Go through the decoded position entries, matching up
     * with original entries.
     */

    List<PositionEntry> decodedEntries = decoder.getPositionList();

    if (decodedEntries.size() != pl.size()) {
      throw new RuntimeException(
          "Decoded positions table not same size was "
              + decodedEntries.size()
              + " expected "
              + pl.size());
    }

    for (PositionEntry entry : decodedEntries) {
      boolean found = false;
      for (int i = pl.size() - 1; i >= 0; i--) {
        PositionList.Entry ple = pl.get(i);

        if (entry.line == ple.getPosition().getLine() && entry.address == ple.getAddress()) {
          found = true;
          break;
        }
      }

      if (!found) {
        throw new RuntimeException(
            "Could not match position entry: " + entry.address + ", " + entry.line);
      }
    }

    /*
     * Go through the original local list, in order, matching up
     * with decoded entries.
     */

    List<LocalEntry> decodedLocals = decoder.getLocals();
    int thisStringIdx = decoder.thisStringIdx;
    int decodedSz = decodedLocals.size();
    int paramBase = decoder.getParamBase();

    /*
     * Preflight to fill in any parameters that were skipped in
     * the prologue (including an implied "this") but then
     * identified by full signature.
     */
    for (int i = 0; i < decodedSz; i++) {
      LocalEntry entry = decodedLocals.get(i);
      int idx = entry.nameIndex;

      if ((idx < 0) || (idx == thisStringIdx)) {
        for (int j = i + 1; j < decodedSz; j++) {
          LocalEntry e2 = decodedLocals.get(j);
          if (e2.address != 0) {
            break;
          }
          if ((entry.reg == e2.reg) && e2.isStart) {
            decodedLocals.set(i, e2);
            decodedLocals.remove(j);
            decodedSz--;
            break;
          }
        }
      }
    }

    int origSz = ll.size();
    int decodeAt = 0;
    boolean problem = false;

    for (int i = 0; i < origSz; i++) {
      LocalList.Entry origEntry = ll.get(i);

      if (origEntry.getDisposition() == LocalList.Disposition.END_REPLACED) {
        /*
         * The encoded list doesn't represent replacements, so
         * ignore them for the sake of comparison.
         */
        continue;
      }

      LocalEntry decodedEntry;

      do {
        decodedEntry = decodedLocals.get(decodeAt);
        if (decodedEntry.nameIndex >= 0) {
          break;
        }
        /*
         * A negative name index means this is an anonymous
         * parameter, and we shouldn't expect to see it in the
         * original list. So, skip it.
         */
        decodeAt++;
      } while (decodeAt < decodedSz);

      int decodedAddress = decodedEntry.address;

      if (decodedEntry.reg != origEntry.getRegister()) {
        System.err.println("local register mismatch at orig " + i + " / decoded " + decodeAt);
        problem = true;
        break;
      }

      if (decodedEntry.isStart != origEntry.isStart()) {
        System.err.println("local start/end mismatch at orig " + i + " / decoded " + decodeAt);
        problem = true;
        break;
      }

      /*
       * The secondary check here accounts for the fact that a
       * parameter might not be marked as starting at 0 in the
       * original list.
       */
      if ((decodedAddress != origEntry.getAddress())
          && !((decodedAddress == 0) && (decodedEntry.reg >= paramBase))) {
        System.err.println("local address mismatch at orig " + i + " / decoded " + decodeAt);
        problem = true;
        break;
      }

      decodeAt++;
    }

    if (problem) {
      System.err.println("decoded locals:");
      for (LocalEntry e : decodedLocals) {
        System.err.println("  " + e);
      }
      throw new RuntimeException("local table problem");
    }
  }
Validates an encoded debug info stream against data used to encode it, throwing an exception if
they do not match. Used to validate the encoder.

@param info encoded debug info
@param file {@code non-null;} file to refer to during decoding
@param ref {@code non-null;} method whose info is being decoded
@param code {@code non-null;} original code object that was encoded
@param isStatic whether the method is static
android/android_framework/dex-maker/src/main/java/com/android/dx/dex/file/DebugInfoDecoder.java