Motorola vient de sortir un téléphone Android basé sur x86. Je suis un peu confus quant à la façon dont les applications/bibliothèques natives écrites pour ARM (netflix par exemple) peuvent fonctionner sur ce téléphone.
Je serais reconnaissant si quelqu'un pouvait expliquer.
Oui, le code natif ARM fonctionne sur Intel x86 à l'aide d'une fonction d'émulation nommée Houdini
Cette bibliothèque lit les instructions ARM à la volée et les convertit en instructions x86 équivalentes. C'est la raison pour laquelle de nombreuses applications peuvent fonctionner telles quelles sur x86 sans avoir à créer une bibliothèque équivalente.
Vous pouvez réellement inclure différents codes natifs pour différentes architectures, vous ne savez pas comment Netflix fonctionne, mais si vous ouvrez apk, vous pouvez voir /lib/armeabi-v7a/
. Je suppose donc qu'il peut exister un dossier du type /lib/x86/
Edit: Je viens de vérifier l’application Amazon Shopping, elle possède un code natif pour arm et x86. Alors peut-être que Netflix le fait aussi.
L'émulateur Android Studio 3 utilise QEMU comme backend
https://en.wikipedia.org/wiki/QEMU
QEMU est sans doute le premier émulateur cross-open open source. Il s’agit d’un logiciel sous licence GPL, qui prend en charge de nombreux autres archs en plus de x86 et d’ARM.
Ensuite, Android ajoute juste un peu de magie d’interface utilisateur au-dessus de QEMU et éventuellement des correctifs, mais le noyau est définitivement dans QEMU en amont.
QEMU utilise une technique appelée traduction binaire pour obtenir une émulation relativement rapide: https://en.wikipedia.org/wiki/Binary_translation
La traduction binaire traduit essentiellement ARM - instructions en instructions x86 équivalentes.
Par conséquent, pour comprendre les détails, le meilleur moyen consiste à:
Théorie
Par conséquent, il est clair que tout processeur peut émuler tout processeur doté de suffisamment de mémoire.
La question difficile est de savoir comment faire cela rapide.
Pratique: Simulation en mode utilisateur QEMU
QEMU a un mode utilisateur qui permet de jouer très facilement avec userland ARM - code sur votre ordinateur x86 pour voir ce qui se passe, tant que votre invité et votre hôte utilisent le même système d’exploitation.
Dans ce mode, la traduction binaire prend en charge les instructions de base et les appels système sont simplement redirigés vers les appels du système hôte.
Par exemple, pour Linux sur Linux avec un monde de salut indépendant de Linux (sans glibc):
main.S
.text
.global _start
_start:
asm_main_after_prologue:
/* write */
mov x0, 1
adr x1, msg
ldr x2, =len
mov x8, 64
svc 0
/* exit */
mov x0, 0
mov x8, 93
svc 0
msg:
.ascii "hello syscall v8\n"
len = . - msg
Puis assemblez et exécutez en tant que:
Sudo apt-get install qemu-user gcc-aarch64-linux-gnu
aarch64-linux-gnu-as -o main.o main.S
aarch64-linux-gnu-ld -o main.out main.o
qemu-aarch64 main.out
et il produit le résultat attendu:
hello syscall v8
Vous pouvez même exécuter ARM - des programmes compilés avec la bibliothèque standard C, puis déboguer le programme par GDB! Voir cet exemple concret: Comment procéder en une seule étape ARM Assemblage dans GDB sur QEMU?
Puisque nous parlons de traduction binaire, nous pouvons également permettre à certains utilisateurs de voir la traduction exacte effectuée par QEMU:
qemu-aarch64 -d in_asm,out_asm main.out
Ici:
in_asm
fait référence à l'assembly ARM input inputout_asm
fait référence à l'assemblage généré par l'hôte X86 qui est exécutéLa sortie contient:
----------------
IN:
0x0000000000400078: d2800020 mov x0, #0x1
0x000000000040007c: 100000e1 adr x1, #+0x1c (addr 0x400098)
0x0000000000400080: 58000182 ldr x2, pc+48 (addr 0x4000b0)
0x0000000000400084: d2800808 mov x8, #0x40
0x0000000000400088: d4000001 svc #0x0
OUT: [size=105]
0x5578d016b428: mov -0x8(%r14),%ebp
0x5578d016b42c: test %ebp,%ebp
0x5578d016b42e: jne 0x5578d016b482
0x5578d016b434: mov $0x1,%ebp
0x5578d016b439: mov %rbp,0x40(%r14)
0x5578d016b43d: mov $0x400098,%ebp
0x5578d016b442: mov %rbp,0x48(%r14)
0x5578d016b446: mov $0x4000b0,%ebp
0x5578d016b44b: mov 0x0(%rbp),%rbp
0x5578d016b44f: mov %rbp,0x50(%r14)
0x5578d016b453: mov $0x40,%ebp
0x5578d016b458: mov %rbp,0x80(%r14)
0x5578d016b45f: mov $0x40008c,%ebp
0x5578d016b464: mov %rbp,0x140(%r14)
0x5578d016b46b: mov %r14,%rdi
0x5578d016b46e: mov $0x2,%esi
0x5578d016b473: mov $0x56000000,%edx
0x5578d016b478: mov $0x1,%ecx
0x5578d016b47d: callq 0x5578cfdfe130
0x5578d016b482: mov $0x7f8af0565013,%rax
0x5578d016b48c: jmpq 0x5578d016b416
ainsi, dans la section IN
, nous voyons notre écriture manuscrite ARM code d'assemblage, et dans la section OUT
, nous voyons l'assembly x86 généré.
Testé sous Ubuntu 16.04 AMD64, QEMU 2.5.0, binutils 2.26.1.
Emulation de système complet QEMU
Cependant, lorsque vous démarrez Android dans QEMU, il ne s'agit pas d'un binaire utilisateur, mais d'une simulation complète du système, qui exécute le noyau Linux et tous les périphériques de la simulation.
La simulation du système complet est plus précise, mais un peu plus lente, et vous devez donner une image de noyau et de disque à QEMU.
Pour l'essayer, jetez un coup d'œil aux configurations suivantes:
KVM
Si vous utilisez Android X86 sur QEMU, vous remarquerez que le processus est beaucoup plus rapide.
La raison en est que QEMU utilise KVM , qui est une fonctionnalité du noyau Linux pouvant exécuter les instructions de l’invité directement sur l’hôte!
Si vous possédez une puissante ARM - machine (encore rare en 2019), vous pouvez également exécuter ARM sur ARM avec KVM Plus vite.
Pour cette raison, je vous recommande de vous en tenir à la simulation AOSP X86 si vous êtes sur un hôte X86, sauf si vous devez vraiment toucher à quelque chose de bas niveau.
Dans Trend Micro Safe Mobile Workforce , nous avons un environnement d'exécution ARM (pas houdini d'Intel) pour la bibliothèque native dans les applications Android. Ainsi, nous pouvons prendre en charge l'exécution de APK avec seulement ARM lib sur un puissant serveur x86.