it-swarm.com.de

Wie funktioniert der native Android-Code? ARM auf x86 laufen?

Motorola hat gerade ein x86-basiertes Android-Handy veröffentlicht. Ich bin etwas verwirrt, wie native Apps/Bibliotheken, die für ARM (beispielsweise Netflix) geschrieben wurden, auf diesem Telefon ausgeführt werden können.

Ich wäre dankbar, wenn mir jemand erklären könnte.

30
Ayush

Ja, der native Code ARM wird unter Intel x86 ausgeführt und verwendet eine Emulationsfunktion mit dem Namen Houdini .

Was diese Bibliothek macht, liest ARM -Anweisungen im Handumdrehen und konvertiert sie in entsprechende x86-Anweisungen. Dies ist der Grund, warum viele Apps wie auf x86 funktionieren, ohne dass eine entsprechende Bibliothek erstellt werden muss.

enter image description here

52
Royston Pinto

Sie können anderen nativen Code für unterschiedliche Architekturen hinzufügen. Sie sind nicht sicher, wie Netflix ausgeführt wird. Wenn Sie jedoch apk öffnen, sehen Sie /lib/armeabi-v7a/. Ich gehe davon aus, dass es einen Ordner wie /lib/x86/ geben kann.

Edit: Ich habe gerade die Amazon-Shopping-App überprüft, da sie nativen Code für Arm und x86 hat. So macht es vielleicht auch Netflix.

9
nandeesh

Der Android Studio 3-Emulator verwendet QEMU als Backend

https://en.wikipedia.org/wiki/QEMU

QEMU ist wohl der führende Open Source Cross Arch Emulator. Es handelt sich um eine GPL-Software, die neben x86 und ARM viele, viele weitere Arches unterstützt.

Android fügt dann ein wenig UI-Magie zu QEMU hinzu und möglicherweise einige Patches, aber der Kern ist definitiv im QEMU-Upstream.

QEMU verwendet eine als binäre Übersetzung bezeichnete Technik, um eine relativ schnelle Emulation zu erreichen: https://en.wikipedia.org/wiki/Binary_translation

Die binäre Übersetzung übersetzt im Wesentlichen ARM Anweisungen in äquivalente x86-Anweisungen.

Um die Details zu verstehen, ist der beste Weg:

  • qEMU-Quellcode lesen: https://github.com/qemu/qemu
  • studieren Sie im Allgemeinen die binäre Übersetzung und schreiben Sie möglicherweise Ihre eigene Implementierung von Spielzeug

Theorie

  • CPUs sind " Turing abgeschlossen " (bis zu Speichergrenzen)
  • CPUs haben ein einfaches deterministisches Verhalten, das mit endlichen Speicher-Turing-Maschinen simuliert werden kann

Es ist daher klar, dass jede CPU jede CPU mit ausreichend Speicherplatz emulieren kann.

Die schwierige Frage ist, wie das fast geht.

Übung: QEMU User Mode Simulation

QEMU verfügt über einen Userland-Modus, der es sehr einfach macht, mit userland ARM Code auf Ihrem x86-Computer zu spielen, um zu sehen, was passiert, solange Gast und Host dasselbe Betriebssystem verwenden.

In diesem Modus erledigt die binäre Übersetzung die grundlegenden Anweisungen, und Systemaufrufe werden nur an die Host-Systemaufrufe weitergeleitet.

Zum Beispiel für Linux unter Linux mit einem freistehenden Linux (keine glibc) Hallo Welt:

netz

.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

GitHub Upstream .

Dann montieren und ausführen als:

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 

und es gibt das erwartete aus:

hello syscall v8

Sie können sogar ARM = Programme ausführen, die mit der C-Standardbibliothek kompiliert wurden, und GDB-Schritte debuggen das Programm! Sehen Sie sich dieses konkrete Beispiel an: How to single step ARM Assembly in GDB auf QEMU?

Da wir über die binäre Übersetzung sprechen, können wir auch die Protokollierung aktivieren, um die genaue Übersetzung zu sehen, die QEMU ausführt:

qemu-aarch64 -d in_asm,out_asm main.out

Hier:

  • in_asm bezieht sich auf die Assembly ARM guest input
  • out_asm bezieht sich auf vom X86-Host generierte Assembly, die ausgeführt wird

Die Ausgabe enthält:

----------------
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 

im Abschnitt IN sehen wir unsere Hand geschrieben ARM Assemblycode, und im Abschnitt OUT sehen wir die generierte x86-Assembly.

Getestet in Ubuntu 16.04 AMD64, QEMU 2.5.0, binutils 2.26.1.

QEMU vollständige Systememulation

Beim Booten von Android in QEMU wird jedoch keine Userland-Binärdatei ausgeführt, sondern eine vollständige Systemsimulation, bei der der eigentliche Linux-Kernel und alle Geräte in der Simulation ausgeführt werden.

Die vollständige Systemsimulation ist genauer, aber etwas langsamer, und Sie müssen QEMU einen Kernel und ein Festplatten-Image geben.

Um das auszuprobieren, werfen Sie einen Blick auf die folgenden Einstellungen:

KVM

Wenn Sie Android X86 auf QEMU ausführen, werden Sie feststellen, dass es wesentlich schneller ist.

Der Grund ist, dass QEMU KVM verwendet, eine Linux-Kernel-Funktion, mit der die Gastanweisungen direkt auf dem Host ausgeführt werden können!

Wenn Sie eine leistungsfähige ARM Maschine haben (noch selten ab 2019), können Sie auch ARM on ARM mit KVM ausführen viel schneller.

Aus diesem Grund empfehle ich Ihnen, sich an der X86-Simulation von AOSP zu halten, wenn Sie sich auf einem X86-Host befinden, es sei denn, Sie müssen wirklich etwas niedrigeres Niveau berühren.

In Trend Micro Safe Mobile Workforce haben wir eine ARM Laufzeit (nicht Intels Houdini) für native Bibliothek in Android-Apps. Damit wir das Ausführen von APK nur mit ARM lib auf einem leistungsstarken x86-Server unterstützen können.

0
Sun Junwen