Esempio n. 1
0
 @Nonnull
 @Override
 public VariableSizeIterator<String> getParameterNames(@Nullable DexReader reader) {
   if (reader == null) {
     reader = dexFile.readerAt(debugInfoOffset);
     reader.skipUleb128();
   }
   // TODO: make sure dalvik doesn't allow more parameter names than we have parameters
   final int parameterNameCount = reader.readSmallUleb128();
   return new VariableSizeIterator<String>(reader, parameterNameCount) {
     @Override
     protected String readNextItem(@Nonnull DexReader reader, int index) {
       return dexFile.getOptionalString(reader.readSmallUleb128() - 1);
     }
   };
 }
Esempio n. 2
0
    @Nonnull
    @Override
    public Iterator<DebugItem> iterator() {
      DexReader reader = dexFile.readerAt(debugInfoOffset);
      final int lineNumberStart = reader.readBigUleb128();
      int registerCount = methodImpl.getRegisterCount();

      // TODO: does dalvik allow references to invalid registers?
      final LocalInfo[] locals = new LocalInfo[registerCount];
      Arrays.fill(locals, EMPTY_LOCAL_INFO);

      DexBackedMethod method = methodImpl.method;

      // Create a MethodParameter iterator that uses our DexReader instance to read the parameter
      // names.
      // After we have finished iterating over the parameters, reader will "point to" the beginning
      // of the
      // debug instructions
      final Iterator<? extends MethodParameter> parameterIterator =
          new ParameterIterator(
              method.getParameterTypes(),
              method.getParameterAnnotations(),
              getParameterNames(reader));

      // first, we grab all the parameters and temporarily store them at the beginning of locals,
      // disregarding any wide types
      int parameterIndex = 0;
      if (!AccessFlags.STATIC.isSet(methodImpl.method.getAccessFlags())) {
        // add the local info for the "this" parameter
        locals[parameterIndex++] =
            new LocalInfo() {
              @Override
              public String getName() {
                return "this";
              }

              @Override
              public String getType() {
                return methodImpl.method.getDefiningClass();
              }

              @Override
              public String getSignature() {
                return null;
              }
            };
      }
      while (parameterIterator.hasNext()) {
        locals[parameterIndex++] = parameterIterator.next();
      }

      if (parameterIndex < registerCount) {
        // now, we push the parameter locals back to their appropriate register, starting from the
        // end
        int localIndex = registerCount - 1;
        while (--parameterIndex > -1) {
          LocalInfo currentLocal = locals[parameterIndex];
          String type = currentLocal.getType();
          if (type != null && (type.equals("J") || type.equals("D"))) {
            localIndex--;
            if (localIndex == parameterIndex) {
              // there's no more room to push, the remaining registers are already in the correct
              // place
              break;
            }
          }
          locals[localIndex] = currentLocal;
          locals[parameterIndex] = EMPTY_LOCAL_INFO;
          localIndex--;
        }
      }

      return new VariableSizeLookaheadIterator<DebugItem>(dexFile, reader.getOffset()) {
        private int codeAddress = 0;
        private int lineNumber = lineNumberStart;

        @Nullable
        protected DebugItem readNextItem(@Nonnull DexReader reader) {
          while (true) {
            int next = reader.readUbyte();
            switch (next) {
              case DebugItemType.END_SEQUENCE:
                {
                  return null;
                }
              case DebugItemType.ADVANCE_PC:
                {
                  int addressDiff = reader.readSmallUleb128();
                  codeAddress += addressDiff;
                  continue;
                }
              case DebugItemType.ADVANCE_LINE:
                {
                  int lineDiff = reader.readSleb128();
                  lineNumber += lineDiff;
                  continue;
                }
              case DebugItemType.START_LOCAL:
                {
                  int register = reader.readSmallUleb128();
                  String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
                  String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
                  ImmutableStartLocal startLocal =
                      new ImmutableStartLocal(codeAddress, register, name, type, null);
                  locals[register] = startLocal;
                  return startLocal;
                }
              case DebugItemType.START_LOCAL_EXTENDED:
                {
                  int register = reader.readSmallUleb128();
                  String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
                  String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
                  String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
                  ImmutableStartLocal startLocal =
                      new ImmutableStartLocal(codeAddress, register, name, type, signature);
                  locals[register] = startLocal;
                  return startLocal;
                }
              case DebugItemType.END_LOCAL:
                {
                  int register = reader.readSmallUleb128();
                  LocalInfo localInfo = locals[register];
                  boolean replaceLocalInTable = true;
                  if (localInfo instanceof EndLocal) {
                    localInfo = EMPTY_LOCAL_INFO;
                    // don't replace the local info in locals. The new EndLocal won't have any info
                    // at all,
                    // and we dont want to wipe out what's there, so that it is available for a
                    // subsequent
                    // RestartLocal
                    replaceLocalInTable = false;
                  }
                  ImmutableEndLocal endLocal =
                      new ImmutableEndLocal(
                          codeAddress,
                          register,
                          localInfo.getName(),
                          localInfo.getType(),
                          localInfo.getSignature());
                  if (replaceLocalInTable) {
                    locals[register] = endLocal;
                  }
                  return endLocal;
                }
              case DebugItemType.RESTART_LOCAL:
                {
                  int register = reader.readSmallUleb128();
                  LocalInfo localInfo = locals[register];
                  ImmutableRestartLocal restartLocal =
                      new ImmutableRestartLocal(
                          codeAddress,
                          register,
                          localInfo.getName(),
                          localInfo.getType(),
                          localInfo.getSignature());
                  locals[register] = restartLocal;
                  return restartLocal;
                }
              case DebugItemType.PROLOGUE_END:
                {
                  return new ImmutablePrologueEnd(codeAddress);
                }
              case DebugItemType.EPILOGUE_BEGIN:
                {
                  return new ImmutableEpilogueBegin(codeAddress);
                }
              case DebugItemType.SET_SOURCE_FILE:
                {
                  String sourceFile = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
                  return new ImmutableSetSourceFile(codeAddress, sourceFile);
                }
              default:
                {
                  int adjusted = next - 0x0A;
                  codeAddress += adjusted / 15;
                  lineNumber += (adjusted % 15) - 4;
                  return new ImmutableLineNumber(codeAddress, lineNumber);
                }
            }
          }
        }
      };
    }