示例#1
0
  /**
   * Reads the file that specifies method calls that should be replaced by other method calls. The
   * file is of the form:
   *
   * <p>[regex] [orig-method-def] [new-method-name]
   *
   * <p>where the orig_method-def is of the form:
   *
   * <p>fully-qualified-method-name (args)
   *
   * <p>Blank lines and // comments are ignored. The orig-method-def is replaced by a call to
   * new-method-name with the same arguments in any classfile that matches the regular expressions.
   * All method names and argument types should be fully qualified.
   */
  public void read_map_file(File map_file) throws IOException {

    LineNumberReader lr = new LineNumberReader(new FileReader(map_file));
    MapFileError mfe = new MapFileError(lr, map_file);
    Pattern current_regex = null;
    Map<MethodDef, MethodInfo> map = new LinkedHashMap<MethodDef, MethodInfo>();
    for (String line = lr.readLine(); line != null; line = lr.readLine()) {
      line = line.replaceFirst("//.*$", "");
      if (line.trim().length() == 0) continue;
      if (line.startsWith(" ")) {
        if (current_regex == null)
          throw new IOException("No current class regex on line " + lr.getLineNumber());
        StrTok st = new StrTok(line, mfe);
        st.stok.wordChars('.', '.');
        MethodDef md = parse_method(st);
        String new_method = st.need_word();
        map.put(md, new MethodInfo(new_method));
      } else {
        if (current_regex != null) {
          MethodMapInfo mmi = new MethodMapInfo(current_regex, map);
          map_list.add(mmi);
          map = new LinkedHashMap<MethodDef, MethodInfo>();
        }
        current_regex = Pattern.compile(line);
      }
    }
    if (current_regex != null) {
      MethodMapInfo mmi = new MethodMapInfo(current_regex, map);
      map_list.add(mmi);
    }

    dump_map_list();
  }
示例#2
0
  public void addUsedConst(int idx, int len) {

    Integer ii = new Integer(idx);

    if (cpoolUsed.contains(ii)) return;
    cpoolUsed.add(ii);
    if (len > 1) {
      // add a dummy entry for a long or double constant
      cpoolUsed.add(null);
    }
    cpoolMap.put(idx, cpoolUsed.indexOf(ii));
  }
示例#3
0
  /**
   * Transforms invoke instructions that match the specified list for this class to call the
   * specified static call instead.
   */
  private InstructionList xform_inst(MethodGen mg, Instruction inst) {

    switch (inst.getOpcode()) {
      case Constants.INVOKESTATIC:
        {
          InstructionList il = new InstructionList();
          INVOKESTATIC is = (INVOKESTATIC) inst;
          String cname = is.getClassName(pgen);
          String mname = is.getMethodName(pgen);
          Type[] args = is.getArgumentTypes(pgen);
          MethodDef orig = new MethodDef(cname + "." + mname, args);
          MethodInfo call = method_map.get(orig);
          if (call != null) {
            call.cnt++;
            String classname = call.method_class;
            String methodname = mname;
            debug_map.log(
                "%s.%s: Replacing method %s.%s (%s) with %s.%s%n",
                mg.getClassName(),
                mg.getName(),
                cname,
                mname,
                UtilMDE.join(args, ", "),
                classname,
                methodname);
            il.append(
                ifact.createInvoke(
                    classname, methodname, is.getReturnType(pgen), args, Constants.INVOKESTATIC));
          }
          return (il);
        }

      case Constants.INVOKEVIRTUAL:
        {
          InstructionList il = new InstructionList();
          INVOKEVIRTUAL iv = (INVOKEVIRTUAL) inst;
          String cname = iv.getClassName(pgen);
          String mname = iv.getMethodName(pgen);
          Type[] args = iv.getArgumentTypes(pgen);
          Type instance_type = iv.getReferenceType(pgen);
          Type[] new_args = BCELUtil.insert_type(instance_type, args);
          MethodDef orig = new MethodDef(cname + "." + mname, args);
          if (debug_class) System.out.printf("looking for %s in map %s%n", orig, method_map);
          MethodInfo call = method_map.get(orig);
          if (call != null) {
            call.cnt++;
            String classname = call.method_class;
            String methodname = mname;
            debug_map.log(
                "Replacing method %s.%s (%s) with %s.%s%n",
                cname, mname, ArraysMDE.toString(args), classname, methodname);
            il.append(
                ifact.createInvoke(
                    classname,
                    methodname,
                    iv.getReturnType(pgen),
                    new_args,
                    Constants.INVOKESTATIC));
          }
          return (il);
        }

      default:
        return (null);
    }
  }
示例#4
0
  public void dump(PrintWriter out, PrintWriter outLinkInfo) {

    int i;

    out.println("//");
    out.println("//\t" + classRefAddress + ": " + clazz.getClassName() + " class info");
    out.println("//");
    out.println("\t\t" + instSize + ",\t//\tinstance size");
    for (i = 0; i < clft.len; ++i) {
      if (!clft.isStatic[i]) {
        out.println("\t\t\t\t//\t" + clft.idx[i] + " " + clft.key[i]);
      }
    }
    // link info: class addresses
    outLinkInfo.println(
        "class " + clazz.getClassName() + " " + methodsAddress + " " + cpoolAddress);
    outLinkInfo.println(" -instSize " + instSize);

    out.println("\t\t" + staticValueVarAddress + ",\t//\tpointer to static primitive fields");
    if (instSize > 31) {
      System.err.println("Error: Object of " + clazz.getClassName() + " to big! Size=" + instSize);
      System.exit(-1);
    }
    out.println("\t\t" + instGCinfo + ",\t//\tinstance GC info");

    String supname = "null";
    int superAddr = 0;
    if (superClass != null) {
      supname = superClass.clazz.getClassName();
      superAddr = ((JopClassInfo) appInfo.cliMap.get(supname)).classRefAddress;
    }
    if (!clazz.isInterface()) {
      out.println("\t\t" + superAddr + ",\t//\tpointer to super class - " + supname);
      // link info: super address
      outLinkInfo.println(" -super " + superAddr);
    } else {
      out.println("\t\t" + (-interfaceID) + ",\t//\tinterface ID");
    }

    boolean useSuperInterfaceTable = false;
    if ((iftableAddress == 0) && (superClass != null)) {
      iftableAddress = ((JopClassInfo) appInfo.cliMap.get(supname)).iftableAddress;
      useSuperInterfaceTable = true;
    }
    out.println("\t\t" + iftableAddress + ",\t//\tpointer to interface table");

    if (!clazz.isInterface()) {
      out.println("//");
      out.println("//\t" + methodsAddress + ": " + clazz.getClassName() + " method table");
      out.println("//");

      int addr = methodsAddress;
      for (i = 0; i < clvt.len; i++) {
        clvt.mi[i].dumpMethodStruct(out, addr);
        outLinkInfo.println(" -mtab " + clvt.mi[i].getFQMethodName() + " " + addr);
        addr += ClassStructConstants.METH_STR;
      }
    } else {
      out.println("//");
      out.println("//\tno method table for interfaces");
      out.println("//");
    }

    out.println();
    out.println("\t\t" + classRefAddress + ",\t//\tpointer back to class struct (cp-1)");
    out.println();

    out.println("//");
    out.println("//\t" + cpoolAddress + ": " + clazz.getClassName() + " constants");
    out.println("//");

    // link info: constant pool mapping
    for (Entry<Integer, Integer> entry : cpoolMap.entrySet()) {
      outLinkInfo.println(" -constmap " + entry.getKey() + " " + entry.getValue());
    }

    // constant pool length includes the length field
    // same is true for the index in the bytecodes:
    // The lowest constant has index 1.
    out.println("\t\t" + (cpoolArry.length + 1) + ",\t//\tconst pool length");
    out.println();
    for (i = 0; i < cpoolArry.length; ++i) {
      out.println("\t\t" + cpoolArry[i] + ",\t//\t" + cpoolComments[i]);
    }

    if (iftableAddress != 0 && !useSuperInterfaceTable) {

      out.println("//");
      out.println(
          "//\t"
              + (iftableAddress - (interfaceCnt + 31) / 32)
              + ": "
              + clazz.getClassName()
              + " implements table");
      out.println("//");
      for (i = (interfaceCnt + 31) / 32 - 1; i >= 0; i--) {
        String comment = "";
        int word = 0;
        int j;
        for (j = 31; j >= 0; j--) {
          word <<= 1;
          if ((i * 32 + j) < interfaceCnt) {
            if (implementsInterface(interfaceList.get(i * 32 + j))) {
              word |= 1;
              comment += interfaceList.get(i * 32 + j) + ", ";
            }
            ;
          }
        }
        out.println("\t\t" + word + ",\t//\t" + comment);
      }

      out.println("//");
      out.println("//\t" + iftableAddress + ": " + clazz.getClassName() + " interface table");
      out.println("//");
      if (!clazz.isInterface()) {
        out.println("//\tTODO: is it enough to use methodId as key???");
        out.println("//");
        for (i = 0; i < listIT.size(); ++i) {
          IT it = (IT) listIT.get(i);
          int j;
          for (j = 0; j < clvt.len; j++) {
            if (clvt.key[j].equals(it.key)) {
              break;
            }
          }
          if (j != clvt.len) {
            out.print("\t\t" + (methodsAddress + j * ClassStructConstants.METH_STR) + ",");
          } else {
            out.print("\t\t" + 0 + ",\t");
          }
          out.println("\t//\t" + it.meth.methodId);
        }
      }
    }
  }