public static void reconstructHeaders(Iterable<NativeLibrary> libraries, PrintWriter out) {
    List<MemberRef> orphanMembers = new ArrayList<MemberRef>();
    Map<TypeRef, List<MemberRef>> membersByClass = new HashMap<TypeRef, List<MemberRef>>();
    for (NativeLibrary library : libraries) {
      for (Symbol symbol : library.getSymbols()) {
        MemberRef mr = symbol.getParsedRef();
        if (mr == null) continue;

        TypeRef et = mr.getEnclosingType();
        if (et == null) orphanMembers.add(mr);
        else {
          List<MemberRef> mrs = membersByClass.get(et);
          if (mrs == null) membersByClass.put(et, mrs = new ArrayList<MemberRef>());
          mrs.add(mr);
        }
      }
    }
    for (TypeRef tr : membersByClass.keySet()) out.println("class " + tr + ";");

    for (MemberRef mr : orphanMembers) out.println(mr + ";");

    for (Map.Entry<TypeRef, List<MemberRef>> e : membersByClass.entrySet()) {
      TypeRef tr = e.getKey();
      List<MemberRef> mrs = e.getValue();
      out.println("class " + tr + " \n{");
      for (MemberRef mr : mrs) {
        out.println("\t" + mr + ";");
      }
      out.println("}");
    }
  }
Beispiel #2
0
 //    @Array(Toto.IBV_SYSFS_NAME_MAX.value)
 public static void print(String name, long addr, int n, int minI) {
   System.out.println(name);
   for (int i = -1; i < n; i++) {
     long v = getPtr(addr + i * Pointer.SIZE);
     Symbol sym = BridJ.getSymbolByAddress(v);
     String sname = sym == null ? null : sym.getName();
     System.out.println("\tOffset " + i + ":\t" + hex(v) + " \t('" + sname + "')");
     if (v == 0 && i >= minI) break;
   }
   System.out.println();
 }
  long getVirtualTable(Type type, NativeLibrary library) {
    Long vtable = vtables.get(type);
    if (vtable == null) {
      final Class<?> typeClass = Utils.getClass(type);
      if (false) {
        String className = typeClass.getSimpleName();
        String vtableSymbol;
        if (Platform.isWindows()) vtableSymbol = "??_7" + className + "@@6B@";
        else vtableSymbol = "_ZTV" + className.length() + className;

        vtables.put(type, vtable = library.getSymbolAddress(vtableSymbol));
      } else {
        Symbol symbol =
            library.getFirstMatchingSymbol(
                new SymbolAccepter() {
                  public boolean accept(Symbol symbol) {
                    return symbol.matchesVirtualTable(typeClass);
                  }
                });
        if (symbol != null) {
          if (BridJ.debug)
            info("Registering vtable of " + Utils.toString(type) + " as " + symbol.getName());
          //                    Pointer<Pointer> pp = pointerToAddress(symbol.getAddress(),
          // Pointer.class);
          //
          //                    for (int i = 0; i < 6; i++) {
          //                        Pointer p = pp.get(i);
          ////                        if (p == null)
          ////                            break;
          //                        String n = p == null ? null :
          // library.getSymbolName(p.getPeer());
          //                        info("\tVtable entry " + i + " = " + p + " (" + n + ")");
          ////                        if (n == null)
          ////                            break;
          //                    }
        } else if (getVirtualMethodsCount(typeClass) > 0)
          error("Failed to find a vtable for type " + Utils.toString(type));

        if (symbol != null) {
          long address = symbol.getAddress();
          vtable = library.isMSVC() ? address : address + 2 * Pointer.SIZE;
        } else {
          vtable = 0L;
        }
        vtables.put(type, vtable); // */
      }
    }
    return vtable;
  }
  CPPDestructor getDestructor(final Class<?> typeClass, Type type, NativeLibrary lib) {
    CPPDestructor destructor = destructors.get(type);
    if (destructor == null) {
      Symbol symbol =
          lib.getFirstMatchingSymbol(
              new SymbolAccepter() {
                public boolean accept(Symbol symbol) {
                  return symbol.matchesDestructor(typeClass);
                }
              });
      if (BridJ.debug && symbol != null)
        info("Registering destructor of " + Utils.toString(type) + " as " + symbol.getName());

      if (symbol != null)
        destructors.put(
            type, destructor = pointerToAddress(symbol.getAddress(), CPPDestructor.class).get());
    }
    return destructor;
  }
    public MemoryOperators(NativeLibrary library) {
      for (Symbol sym : library.getSymbols()) {
        try {
          MemberRef parsedRef = sym.getParsedRef();
          IdentLike n = parsedRef.getMemberName();

          if (SpecialName.New.equals(n))
            newFct =
                pointerToAddress(sym.getAddress())
                    .asDynamicFunction(null, Pointer.class, SizeT.class);
          else if (SpecialName.NewArray.equals(n))
            newFct =
                pointerToAddress(sym.getAddress())
                    .asDynamicFunction(null, Pointer.class, SizeT.class);
          else if (SpecialName.Delete.equals(n))
            newFct =
                pointerToAddress(sym.getAddress())
                    .asDynamicFunction(null, Void.class, Pointer.class);
          else if (SpecialName.DeleteArray.equals(n))
            newFct =
                pointerToAddress(sym.getAddress())
                    .asDynamicFunction(null, Void.class, Pointer.class);

        } catch (Exception ex) {
        }
      }
    }
  DynamicFunction getConstructor(
      final Class<?> typeClass, final Type type, NativeLibrary lib, int constructorId) {
    Pair<Type, Integer> key = new Pair<Type, Integer>(type, constructorId);
    DynamicFunction constructor = constructors.get(key);
    if (constructor == null) {
      try {
        final Constructor<?> constr;
        try {
          constr = findConstructor(typeClass, constructorId, true);

          if (debug) BridJ.info("Found constructor for " + Utils.toString(type) + " : " + constr);
        } catch (NoSuchMethodException ex) {
          if (debug) BridJ.info("No constructor for " + Utils.toString(type));
          return null;
        }
        Symbol symbol =
            lib == null
                ? null
                : lib.getFirstMatchingSymbol(
                    new SymbolAccepter() {
                      public boolean accept(Symbol symbol) {
                        return symbol.matchesConstructor(
                            constr.getDeclaringClass() == Utils.getClass(type)
                                ? type
                                : constr.getDeclaringClass() /* TODO */,
                            constr);
                      }
                    });
        if (symbol == null) {
          if (debug)
            BridJ.info("No matching constructor for " + Utils.toString(type) + " (" + constr + ")");
          return null;
        }

        if (debug) info("Registering constructor " + constr + " as " + symbol.getName());

        // TODO do something with these args !
        int templateParametersCount = getTemplateParametersCount(typeClass);

        Class<?>[] consParamTypes = constr.getParameterTypes();
        Class<?>[] consThisParamTypes =
            new Class[consParamTypes.length + 1 - templateParametersCount];
        consThisParamTypes[0] = Pointer.class;
        System.arraycopy(
            consParamTypes,
            templateParametersCount,
            consThisParamTypes,
            1,
            consParamTypes.length - templateParametersCount);

        DynamicFunctionFactory constructorFactory =
            getDynamicFunctionFactory(lib, Style.ThisCall, void.class, consThisParamTypes);

        constructor = constructorFactory.newInstance(pointerToAddress(symbol.getAddress()));
        constructors.put(key, constructor);
      } catch (Throwable th) {
        th.printStackTrace();
        throw new RuntimeException(
            "Unable to create constructor " + constructorId + " for " + type + " : " + th, th);
      }
    }
    return constructor;
  }
  @Override
  protected void registerNativeMethod(
      Class<?> type,
      NativeLibrary typeLibrary,
      Method method,
      NativeLibrary methodLibrary,
      Builder builder,
      MethodCallInfoBuilder methodCallInfoBuilder)
      throws FileNotFoundException {

    int modifiers = method.getModifiers();
    boolean isCPPClass = CPPObject.class.isAssignableFrom(method.getDeclaringClass());

    //		Annotation[][] anns = method.getParameterAnnotations();
    if (!isCPPClass) {
      super.registerNativeMethod(
          type, typeLibrary, method, methodLibrary, builder, methodCallInfoBuilder);
      return;
    }

    MethodCallInfo mci = methodCallInfoBuilder.apply(method);

    Virtual va = method.getAnnotation(Virtual.class);
    if (va == null) {
      Symbol symbol = methodLibrary.getSymbol(method);
      mci.setForwardedPointer(symbol == null ? 0 : symbol.getAddress());
      if (mci.getForwardedPointer() == 0) {
        assert error(
            "Method "
                + method.toGenericString()
                + " is not virtual but its address could not be resolved in the library.");
        return;
      }
      if (Modifier.isStatic(modifiers)) {
        builder.addFunction(mci);
        if (debug)
          info("Registering " + method + " as function or static C++ method " + symbol.getName());
      } else {
        builder.addFunction(mci);
        if (debug) info("Registering " + method + " as C++ method " + symbol.getName());
      }
    } else {
      if (Modifier.isStatic(modifiers)) {
        warning(
            "Method "
                + method.toGenericString()
                + " is native and maps to a function, but is not static.");
      }

      int theoreticalVirtualIndex = va.value();
      int theoreticalAbsoluteVirtualIndex =
          theoreticalVirtualIndex < 0
              ? -1
              : getAbsoluteVirtualIndex(method, theoreticalVirtualIndex, type);

      int absoluteVirtualIndex;

      Pointer<Pointer<?>> pVirtualTable =
          isCPPClass && typeLibrary != null
              ? (Pointer) pointerToAddress(getVirtualTable(type, typeLibrary), Pointer.class)
              : null;
      if (pVirtualTable == null) {
        if (theoreticalAbsoluteVirtualIndex < 0) {
          error(
              "Method "
                  + method.toGenericString()
                  + " is virtual but the virtual table of class "
                  + type.getName()
                  + " was not found and the virtual method index is not provided in its @Virtual annotation.");
          return;
        }
        absoluteVirtualIndex = theoreticalAbsoluteVirtualIndex;
      } else {
        int guessedAbsoluteVirtualIndex =
            getPositionInVirtualTable(pVirtualTable, method, typeLibrary);
        if (guessedAbsoluteVirtualIndex < 0) {
          if (theoreticalAbsoluteVirtualIndex < 0) {
            error(
                "Method "
                    + method.toGenericString()
                    + " is virtual but its position could not be found in the virtual table.");
            return;
          } else {
            absoluteVirtualIndex = theoreticalAbsoluteVirtualIndex;
          }
        } else {
          if (theoreticalAbsoluteVirtualIndex >= 0
              && guessedAbsoluteVirtualIndex != theoreticalAbsoluteVirtualIndex) {
            warning(
                "Method "
                    + method.toGenericString()
                    + " has @Virtual annotation indicating virtual index "
                    + theoreticalAbsoluteVirtualIndex
                    + ", but analysis of the actual virtual table rather indicates it has index "
                    + guessedAbsoluteVirtualIndex
                    + " (using the guess)");
          }
          absoluteVirtualIndex = guessedAbsoluteVirtualIndex;
        }
      }
      mci.setVirtualIndex(absoluteVirtualIndex);
      if (debug)
        info(
            "Registering "
                + method.toGenericString()
                + " as virtual C++ method with absolute virtual table index = "
                + absoluteVirtualIndex);
      builder.addVirtualMethod(mci);
    }
  }