3 votes

Est-il possible d'annoter le nom de la fonction exportée ?

J'ai l'interface suivante, qui correspond à une fonction exportée d'une DLL :

interface Foo extends Library {
    int ProcessBytes(byte[] bytes, int size);
}

J'utilise Proguard pour obscurcir mon application. Et, pour l'instant, j'utilise l'option -keep pour maintenir le code de l'interface ci-dessus. Ainsi, JNA peut trouver la fonction et l'appeler.

J'aimerais également obscurcir l'interface. Si j'enlève le -keep mon interface ressemblera à ceci :

interface a extends Library {
    int a(byte[] a, int b);
}

Et la JNA ne peut pas s'en charger, car a n'existe pas dans les fonctions exportées. Ma question est donc la suivante : est-il possible d'annoter le nom de la fonction exportée ? Quelque chose comme ceci :

interface Foo extends Library {  
   @Function("ProcessBytes")
   int anyname(byte[] bytes, int size);
}

Comme "Je me fiche du nom de votre méthode, j'appellerai la " ProcessBytes "lorsque la méthode anyname est appelé.

1voto

cubrr Points 4061

Vous pouvez créer une annotation personnalisée et utiliser un élément de type FunctionMapper pour résoudre le nom de la fonction. Cette classe peut être transmise à JNA lors du chargement d'une bibliothèque avec l'option loadLibrary .

@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface NativeFunctionName {
    String name() default "";
}

class FunctionNameAnnotationMapper implements FunctionMapper {
    @Override
    public String getFunctionName(NativeLibrary nativeLibrary, Method method) {
        NativeFunctionName annotation = method.getAnnotation(NativeFunctionName.class);
        // just return the function's name if the annotation is not applied
        return annotation == null ? method.getName() : annotation.name();
    }
}

L'utilisation serait la suivante :

public class Program {
    public static void main(String... args) {
        Map<String, Object> opts = new HashMap<>();
        opts.put(Library.OPTION_FUNCTION_MAPPER, new FunctionNameAnnotationMapper());

        Obfuscated lib = Native.loadLibrary("my-library", Obfuscated.class, opts);
        lib.obfuscated1(0, null);
    }
}

interface Obfuscated extends Library {
    @NativeFunctionName(name = "main")
    public int obfuscated1(int argc, Pointer argv);
}

Notez que la JVM devra accéder à ces valeurs d'annotation pendant l'exécution, et qu'elles seront donc incluses dans la sortie. Assurez-vous que votre obfuscateur conserve ces annotations.

Si vous utilisez déjà un mappeur de fonctions, envisagez de créer une classe de mappeur de fonctions "agrégé" qui vous permettra de passer plusieurs mappeurs.

Pour en savoir plus sur la cartographie des fonctions, cliquez ici : http://java-native-access.github.io/jna/4.5.0/javadoc/overview-summary.html#function-mapping

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X