ASM en ligne en Java

Depuis que j’ai démarré un petit projet visant à incorporer asm pour les processeurs Intel x86 64 bits dans Java et à exécuter et à comstackr ces méthodes (et peut-être plus tard à émuler ces appels), je me demande s’il existe déjà une implémentation Java d’un compilateur x86. Je veux aussi un soutien pour ces instructions avancées.

Le but est finalement d’avoir quelque chose comme:

public int myJavaMethod(long value) { doSomeJavaStuff... int result = 0; asm(" push eax", " mov eax, value", " cmp eax, 0", " jne notEqual", " mov result, 1", " jmp done", "notEqual: mov result, 0", "done: pop eax"); doSomeMoreJavaStuff(); return result; } 

Ce que j’ai:

  • Le manuel d’Intel pour leurs codes OPCodes et l’architecture (VOL2)
  • Je peux officiellement comstackr et exécuter un composant de programme asm (“nop”) en utilisant maintenant la JNA

Défis actuels:

En raison de la nature de la tâche, j’essaierai d’accéder aux frameworks de stack JavaVM sous-jacents – ce qui est possible (rappelez-vous que vous obtenez le pointeur de stack esp et le pointeur de base ebp, même avec les adresses que l’opérateur rétablira dans le pointeur eip). mais couple la solution avec une certaine cible de construction java VM +, ce qui ne me pose pas de problème, car on peut créer différents adaptateurs de cible et il est amusant et intéressant de chercher dans les implémentations de JavaVM.

Un problème avec la solution basée sur une chaîne ci-dessus serait le traitement des parameters et des résultats. Il peut être nécessaire de fournir un mappage de parameters comme asm (params (résultat, valeur, peu importe), “opcodes”) et de placer les variables de sortie soit directement dans les bons emplacements de mémoire, soit dans les registres utilisés par JIT pour remplir les variables dans l’appel à params. ou faites quelque chose comme resultat = asmResult (result) pour lire la valeur modifiée réelle à partir de la section de données de l’appel asm et la placer dans la valeur correcte.

En utilisant Unsafe sur ces informations, on peut même accéder aux variables Object et Class et naviguer dans ces valeurs en obtenant les adresses et les types de toutes les références utilisées dans le code asm. Donc, utiliser asm (“mov eax, super.field”) serait possible sans interférer avec Java – à moins que le JIT ne réalise à nouveau une optimisation intéressante sur la mise en cache du registre, mais pourrait être improbable car asm (…) est un certain appel et un object de mise en cache un contenu variable peut violer les conditions de concurrence d’access relatives aux objects. Mais encore une fois, c’est une question pour les développeurs JVM d’Oracle.

Donc, si vous avez des informations sur le code Java existant ou le code C qui peuvent m’aider avec quoi que ce soit du genre, soyez les bienvenus.

La meilleure aide serait une implémentation Java d’un compilateur x86 qui dispose déjà de moyens pour traduire certaines constructions asm en une série d’octets (codes d’opération) afin que je puisse simplement créer une vraie méthode ASM à partir des appels ci-dessus et des informations. recueillies en inspectant le code octet des méthodes avec Unsafe et quelle que soit la source d’information.

En fin de compte, je veux juste écrire un assembleur dans mon code Java sans aller trop loin et comstackr c / ASM, charger des bibliothèques d’expédition pour différents systèmes d’exploitation et plates-formes. N’a pas de sens. Une fois que cela fonctionne, vous pouvez facilement générer des appels de fonction “C” à la demande et même éventuellement éviter à la JNA de se débarrasser d’une autre dépendance.

Donc, si vous connaissez du code et des projets ou avez des informations supplémentaires, vous êtes le bienvenu.

[Mettre à jour]

Cette question ne vise pas la JNI / JNA. L’objective est simplement de contourner l’utilisation d’un compilateur extraterrestre et de charger une bibliothèque. L’idée est simplement de comstackr en mémoire directement à partir de Java et de démarrer la méthode en utilisant un pointeur sur celle-ci ainsi que des données supplémentaires pour le traitement des parameters et des valeurs.

Il suffit de penser à cette écriture de stream de travail C / ASM, comstackr en utilisant gcc, loadLibrary, méthode d’appel par JNA dans la compilation de stream de travail (en utilisant Java) en mémoire, méthode d’appel par JNA. Je peux déjà faire cela. Je veux juste utiliser plus de codes op sans créer mon propre frontal de compilateur. Il ne s’agit pas de savoir si cela est possible mais de savoir comment le faire paresseusement.

Mais une fois que j’ai démontré la faisabilité de base, je suppose que les gens vont append de nouvelles plates-formes cibles (je ne cible que les processeurs Linux et i5 + Intel Xeon v3).

[Mise à jour 2]

Actuellement, j’étudie le compilateur NASM comme étant mentionné comme un compilateur développé activement et utilisant la notation Intel. J’ai déjà demandé aux développeurs comment une intégration transparente, simple et rapide (sans access au disque par exemple) serait possible. Si cela fonctionne, créer une solution similaire pour C en utilisant un compilateur populaire serait également possible.

L’idée est de modifier le code source Java dans Eclipse, programme exécuté. La compilation de ces extraits dans une langue différente et l’invocation, ainsi que tous les autres éléments amusants, doivent être complètement transparents.

Je ne vois pas comment vous pouvez réellement faire cela. Je pense que vous manquez beaucoup de choses ici, les principales choses qui vous viennent à l’esprit lors d’une première pensée:

  • Java est compilé en bytecode, ce qui est loin de l’assemblage d’Intel. La JVM est une machine basée sur une stack, alors que les processeurs Intel sont (principalement) basés sur des registres.
  • Java n’a pas d’access direct au matériel ni aux appels système puisqu’il s’exécute sur une machine virtuelle, alors que la plupart des assemblys en ligne sont utilisés à cette fin.
  • Ne fonctionnera pas sur des processeurs non-Intel (mais je suppose que vous en avez déjà tenu compte), et vous devrez probablement aussi cibler un système d’exploitation spécifique si vous prévoyez de faire des appels système, ce qui annulera l’un des principaux (oubliés). ) les objectives de Java.
  • Vous aurez probablement besoin d’une machine virtuelle Java personnalisée pour pouvoir exécuter directement des instructions natives.

Cela pourrait être théoriquement possible, mais ce n’est certainement pas une mince affaire.

Si vous vouliez parler d’un assembleur ou d’un émulateur Intel en Java, c’est une autre histoire.