Apakah binari portabel di berbagai arsitektur CPU?


16

Tujuan saya adalah untuk dapat mengembangkan Linux tertanam. Saya memiliki pengalaman pada sistem tertanam bare-metal menggunakan ARM.

Saya punya beberapa pertanyaan umum tentang pengembangan untuk target cpu yang berbeda. Pertanyaan saya adalah sebagai berikut:

  1. Jika saya memiliki aplikasi yang dikompilasi untuk dijalankan pada ' target x86, linux OS versi xyz ', dapatkah saya menjalankan biner yang dikompilasi yang sama pada sistem lain ' target ARM, OS linux versi xyz '?

  2. Jika di atas tidak benar, satu-satunya cara adalah mendapatkan kode sumber aplikasi untuk membangun kembali / mengkompilasi ulang menggunakan toolchain yang relevan 'misalnya, arm-linux-gnueabi'?

  3. Demikian pula, jika saya memiliki modul kernel (driver perangkat) yang dapat dimuat yang bekerja pada ' target x86, OS linux versi xyz ', dapatkah saya memuat / menggunakan .ko yang dikompilasi sama pada sistem lain ' target ARM, OS Linux versi xyz ' ?

  4. Jika di atas tidak benar, satu-satunya cara adalah mendapatkan kode sumber driver untuk membangun kembali / mengkompilasi ulang menggunakan toolchain yang relevan 'misalnya, arm-linux-gnueabi'?


27
tidak, ya, tidak, ya.
hobbs

7
Ini membantu untuk menyadari bahwa kita tidak memiliki target AMD dan target Intel, hanya target x86 tunggal untuk keduanya. Itu karena Intel dan AMD cukup kompatibel. Maka menjadi jelas bahwa target ARM ada karena alasan tertentu, yaitu karena CPU ARM tidak kompatibel dengan Intel / AMD / x86.
MSalters

1
Tidak, kecuali bytecode yang dirancang untuk berjalan di lingkungan runtime portabel seperti Java Runtime. Jika Anda menulis kode untuk penggunaan tertanam, kode Anda kemungkinan akan bergantung pada optimasi atau fitur khusus prosesor tingkat rendah dan akan sangat sulit untuk port, membutuhkan lebih dari sekedar kompilasi untuk platform target (misalnya perubahan kode perakitan, mungkin penulisan ulang beberapa modul atau seluruh program).
bwDraco

1
@MSalters: Sebenarnya, kami memiliki target AMD: amd64 yang sering diberi label x86-64 (sedangkan x86 biasanya merupakan pelabelan ulang i386). Untungnya Intel menyalin (dan kemudian memperluas) arsitektur AMD sehingga x86 64 bit apa pun dapat menjalankan binari amd64.
slebetman

Jawaban:


42

Tidak. Binari harus dikompilasi ulang untuk arsitektur target, dan Linux tidak menawarkan apa pun seperti biner gemuk . Alasannya adalah karena kode tersebut dikompilasi ke kode mesin untuk arsitektur tertentu, dan kode mesin sangat berbeda antara sebagian besar keluarga prosesor (ARM dan x86 misalnya sangat berbeda).

EDIT: perlu dicatat bahwa beberapa arsitektur menawarkan tingkat kompatibilitas ke belakang (dan bahkan lebih jarang, kompatibilitas dengan arsitektur lain); pada CPU 64-bit, umumnya memiliki kompatibilitas mundur ke edisi 32-bit (tapi ingat: pustaka dependen Anda juga harus 32-bit, termasuk pustaka standar C Anda, kecuali jika Anda terhubung secara statis ). Yang juga perlu disebutkan adalah Itanium , di mana dimungkinkan untuk menjalankan kode x86 (hanya 32-bit), meskipun sangat lambat; kecepatan eksekusi kode x86 yang buruk setidaknya merupakan bagian dari alasan itu tidak terlalu sukses di pasar.

Ingatlah bahwa Anda masih tidak dapat menggunakan binari yang dikompilasi dengan instruksi yang lebih baru pada CPU lama, bahkan dalam mode kompatibilitas (misalnya, Anda tidak dapat menggunakan AVX dalam biner 32-bit pada prosesor Nehalem x86 ; CPU hanya tidak mendukungnya.

Perhatikan bahwa modul kernel harus dikompilasi untuk arsitektur yang relevan; selain itu, modul kernel 32-bit tidak akan berfungsi pada kernel 64-bit atau sebaliknya.

Untuk informasi tentang binari lintas-kompilasi (sehingga Anda tidak harus memiliki toolchain pada perangkat ARM target), lihat jawaban komprehensif grochmal di bawah ini.


1
Mungkin perlu diklarifikasi tentang kompatibilitas (atau ketiadaan) antara x86 dan x64, mengingat beberapa binari x86 dapat berjalan pada platform x64. (Saya tidak yakin ini adalah kasus di Linux, tetapi pada Windows, misalnya.)
jpmc26

4
@ jpmc26 dimungkinkan di Linux; tetapi Anda mungkin perlu menginstal perpustakaan kompatibilitas terlebih dahulu. Dukungan x86 adalah bagian non-opsional dari pemasangan Win64. Di Linux itu opsional; dan karena dunia Linux jauh lebih jauh dalam membuat versi 64bit dari segala sesuatu yang tersedia beberapa distro tidak default untuk memiliki (semua?) perpustakaan 32bit diinstal. (Saya tidak yakin bagaimana umum itu adalah;. Tetapi telah melihat beberapa pertanyaan tentang hal itu dari orang-orang yang menjalankan distro mainstreamish sebelumnya)
Dan adalah mengutak-atik oleh Firelight

@ jpmc26 Saya memperbarui jawaban saya dengan catatan Anda; Saya berpikir tentang menyebutkan itu tetapi tidak ingin menyulitkan jawabannya.
Elizafox

16

Elizabeth Myers benar, setiap arsitektur memerlukan biner yang dikompilasi untuk arsitektur yang dimaksud. Untuk membangun binari untuk arsitektur yang berbeda dari yang dijalankan oleh sistem Anda, Anda memerlukan cross-compiler.


Dalam kebanyakan kasus, Anda perlu mengkompilasi cross compiler. Saya hanya punya pengalaman dengan gcc(tapi saya percaya itu llvm, dan kompiler lain, memiliki parameter yang sama). Sebuah gcccross-compiler dicapai dengan menambahkan --targetke configure:

./configure --build=i686-arch-linux-gnu --target=arm-none-linux-gnueabi

Anda perlu mengkompilasi gcc, glibcdan binutilsdengan parameter-parameter ini (dan berikan header kernel dari kernel pada mesin target).

Dalam prakteknya ini jauh lebih rumit dan kesalahan pembangunan yang berbeda muncul pada sistem yang berbeda.

Ada beberapa panduan di luar sana tentang cara mengkompilasi GNU toolchain tetapi saya akan merekomendasikan Linux From Scratch , yang terus dipelihara dan melakukan pekerjaan yang sangat baik dalam menjelaskan apa yang dilakukan perintah yang disajikan.

Pilihan lain adalah kompilasi bootstrap dari cross-compiler. Berkat perjuangan menyusun kompiler silang untuk berbagai arsitektur pada arsitektur yang berbeda crosstool-ngtelah dibuat. Ini memberikan bootstrap di atas toolchain yang dibutuhkan untuk membangun kompiler silang.

crosstool-ngmendukung beberapa kembar tiga target pada arsitektur yang berbeda, pada dasarnya ini adalah bootstrap di mana orang mendedikasikan waktu mereka untuk menyelesaikan masalah yang terjadi selama kompilasi toolchain lintas-kompiler.


Beberapa distro menyediakan cross-compiler sebagai paket:

Dengan kata lain, periksa apa yang tersedia di distro Anda dalam hal kompiler silang. Jika distro Anda tidak memiliki cross compiler untuk kebutuhan Anda, Anda selalu dapat mengompilasinya sendiri.

Referensi:


Modul kernel perlu diperhatikan

Jika Anda mengkompilasi cross-compiler dengan tangan, Anda memiliki semua yang Anda perlukan untuk mengkompilasi modul kernel. Ini karena Anda memerlukan header kernel untuk dikompilasi glibc.

Tetapi, jika Anda menggunakan cross-compiler yang disediakan oleh distro Anda, Anda akan membutuhkan header kernel dari kernel yang berjalan pada mesin target.


FWIW Fedora juga menyertakan cross-compiler.
mattdm

@mattdm - terima kasih, jawab tweak, saya yakin saya mendapat bagian kanan dari fedora wiki yang ditautkan.
grochmal

2
Cara yang lebih mudah daripada Linux From Scratch untuk mendapatkan Linux dan toolchain untuk arsitektur lain crosstool-ng. Anda mungkin ingin menambahkannya ke daftar. Juga, mengonfigurasi dan menyusun GNU cross-toolchain dengan tangan untuk arsitektur apa pun sangat melibatkan dan jauh lebih membosankan daripada sekadar --targetflag. Saya menduga itu adalah bagian dari mengapa LLVM mendapatkan popularitas; Ini dirancang sedemikian rupa sehingga Anda tidak perlu membangun kembali untuk menargetkan arsitektur lain - sebagai gantinya Anda dapat menargetkan beberapa backend menggunakan perpustakaan frontend dan optimizer yang sama.
Iwillnotexist Idonotexist

@IwillnotexistIdonotexist - terima kasih, saya telah mengubah jawabannya lebih lanjut. Saya belum pernah mendengar crosstool-ng sebelumnya, dan itu terlihat sangat berguna. Komentar Anda sebenarnya sangat berguna bagi saya.
grochmal

9

Perhatikan bahwa sebagai upaya terakhir (yaitu ketika Anda tidak memiliki kode sumber), Anda dapat menjalankan binari pada arsitektur yang berbeda menggunakan emulator seperti qemu, dosboxatau exagear. Beberapa emulator dirancang untuk meniru sistem selain Linux (mis. dosboxDirancang untuk menjalankan program MS-DOS, dan ada banyak emulator untuk konsol game populer). Emulasi memiliki overhead kinerja yang signifikan: program yang diemulasi berjalan 2-10 kali lebih lambat daripada rekan aslinya.

Jika Anda perlu menjalankan modul kernel pada CPU non-asli, Anda harus meniru seluruh OS termasuk kernel untuk arsitektur yang sama. AFAIK tidak mungkin menjalankan kode asing di dalam kernel Linux.


3
Penalti kecepatan untuk emulasi seringkali bahkan lebih tinggi dari 10x, tetapi jika seseorang mencoba menjalankan kode yang ditulis untuk mesin 16Mhz pada mesin 4GHz (perbedaan dalam kecepatan 250: 1) emulator yang memiliki penalti kecepatan 50: 1 mungkin masih jalankan kode jauh lebih cepat daripada yang seharusnya dijalankan pada platform asli.
supercat

7

Tidak hanya binari yang tidak portabel antara x86 dan ARM, ada berbagai rasa ARM .

Yang mungkin Anda temui dalam praktik adalah ARMv6 vs ARMv7. Raspberry Pi 1 adalah ARMv6, versi selanjutnya adalah ARMv7. Jadi dimungkinkan untuk mengkompilasi kode pada kode yang lebih baru yang tidak berfungsi pada Pi 1.

Untungnya salah satu manfaat open source dan perangkat lunak bebas adalah memiliki sumber sehingga Anda dapat membangunnya kembali pada arsitektur apa pun. Meskipun ini mungkin memerlukan beberapa pekerjaan.

(Versi ARM membingungkan, tetapi jika ada V sebelum angka itu berbicara tentang arsitektur set instruksi (ISA). Jika tidak ada, itu adalah nomor model seperti "Cortex M0" atau "ARM926EJS". Nomor model tidak ada hubungannya dengan lakukan dengan nomor ISA.)


2
... dan kemudian ada bahkan subflavour yang berbeda untuk rasa ARM yang sama, dan bahkan ABI yang berbeda untuk perangkat keras yang sama persis (saya sedang memikirkan seluruh ARM soft / softfp / hard floating point mess).
Matteo Italia

1
@MatteoItalia Ugh. Beberapa ABI adalah snafu, obat untuk sesuatu yang lebih buruk daripada penyakit. Beberapa ARM tidak memiliki register VFP atau NEON sama sekali, beberapa memiliki 16, 32. Pada Cortex-A8 dan sebelumnya mesin NEON menjalankan selusin CC di belakang inti, jadi mentransfer output vektor ke GPR membutuhkan biaya banyak. ARM telah mendapatkan untuk melakukan hal yang benar - mandat subset fitur umum yang besar.
Iwillnotexist Idonotexist

7

Anda selalu perlu menargetkan sebuah platform yang. Dalam kasus yang paling sederhana, CPU target langsung menjalankan kode yang dikompilasi dalam biner (ini kira-kira sesuai dengan executable COM MS DOS). Mari kita pertimbangkan dua platform berbeda yang baru saja saya temukan - Armistice dan Intellio. Dalam kedua kasus, kita akan memiliki program hello world sederhana yang menghasilkan 42 di layar. Saya juga akan berasumsi bahwa Anda menggunakan bahasa multi-platform dengan cara platform-agnostik, jadi kode sumbernya sama untuk keduanya:

Print(42)

Pada Armistice, Anda memiliki driver perangkat sederhana yang menangani pencetakan angka, jadi yang harus Anda lakukan hanyalah output ke port. Dalam bahasa rakitan portabel kami, ini akan sesuai dengan sesuatu seperti ini:

out 1234h, 42

Namun, atau sistem Intellio tidak memiliki hal seperti itu, sehingga harus melalui lapisan lain:

mov a, 10h
mov c, 42
int 13h

Ups, kami sudah memiliki perbedaan yang signifikan antara keduanya, bahkan sebelum kami sampai ke kode mesin! Ini kira-kira akan sesuai dengan jenis perbedaan yang Anda miliki antara Linux dan MS DOS, atau IBM PC dan X-Box (meskipun keduanya dapat menggunakan CPU yang sama).

Tapi itulah gunanya OS. Mari kita asumsikan kita memiliki HAL yang memastikan bahwa semua konfigurasi perangkat keras yang berbeda ditangani dengan cara yang sama pada lapisan aplikasi - pada dasarnya, kita akan menggunakan pendekatan Intellio bahkan pada Gencatan Senjata, dan kode "rakitan portabel" kami berakhir sama. Ini digunakan oleh sistem mirip Unix modern dan Windows, seringkali bahkan dalam skenario tertanam. Bagus - sekarang kita dapat memiliki kode perakitan yang benar-benar portabel di Armistice dan Intellio. Tapi bagaimana dengan binari?

Seperti yang kita asumsikan, CPU perlu mengeksekusi biner secara langsung. Mari kita lihat baris pertama dari kode kita mov a, 10h, di Intellio:

20 10

Oh Ternyata yang mov a, constantsangat populer itu memiliki instruksi sendiri, dengan opcode sendiri. Bagaimana Gencatan Senjata menangani ini?

36 01 00 10

Hmm. Ada opcode untuknya mov.reg.imm, jadi kita perlu argumen lain untuk memilih register yang akan kita gunakan. Dan konstanta selalu berupa kata 2-byte, dalam notasi big-endian - begitulah Armistice dirancang, pada kenyataannya, semua instruksi dalam Armistice sepanjang 4 byte, tanpa pengecualian.

Sekarang bayangkan menjalankan biner dari Intellio on Armistice: CPU mulai mendekode instruksi, menemukan opcode 20h. Pada Gencatan Senjata, ini sesuai, katakanlah, dengan and.imm.reginstruksi. Mencoba membaca konstanta 2 byte kata (yang berbunyi 10XX, sudah menjadi masalah), dan kemudian nomor register (yang lain XX). Kami menjalankan instruksi yang salah, dengan argumen yang salah. Dan lebih buruknya, instruksi selanjutnya akan menjadi palsu, karena kami benar-benar memakan instruksi lain, mengira itu adalah data.

Aplikasi tidak memiliki peluang untuk bekerja, dan kemungkinan besar akan crash atau hang segera.

Sekarang, ini tidak berarti bahwa executable selalu perlu mengatakan itu dijalankan pada Intellio atau Armistice. Anda hanya perlu mendefinisikan platform yang independen terhadap CPU (sepertibash pada Unix), atau CPU dan OS (seperti Java atau .NET, dan saat ini bahkan JavaScript, semacam). Dalam hal ini, aplikasi dapat menggunakan satu yang dapat dieksekusi untuk semua CPU dan OS yang berbeda, sementara ada beberapa aplikasi atau layanan pada sistem target (yang menargetkan CPU dan / atau OS secara langsung) yang menerjemahkan kode platform-independen ke dalam sesuatu yang CPU sebenarnya bisa dieksekusi. Ini mungkin atau mungkin tidak datang dengan hit kinerja, biaya atau kemampuan.

CPU biasanya berasal dari keluarga. Sebagai contoh, semua CPU dari keluarga x86 memiliki serangkaian instruksi umum yang dikodekan dengan cara yang persis sama, sehingga setiap CPU x86 dapat menjalankan setiap program x86, selama ia tidak mencoba menggunakan ekstensi apa pun (misalnya, operasi floating point atau operasi vektor). Pada x86, contoh paling umum saat ini adalah Intel dan AMD, tentu saja. Atmel adalah perusahaan terkenal yang mendesain CPU dalam keluarga ARM, cukup populer untuk perangkat embedded. Apple juga memiliki CPU ARM sendiri, misalnya.

Tetapi ARM sama sekali tidak kompatibel dengan x86 - mereka memiliki persyaratan desain yang sangat berbeda, dan memiliki sedikit persamaan. Instruksi memiliki opcode yang sama sekali berbeda, mereka didekodekan dengan cara yang berbeda, alamat memori diperlakukan berbeda ... Mungkin dimungkinkan untuk membuat biner yang berjalan pada CPU x86 dan CPU ARM, dengan menggunakan beberapa operasi yang aman untuk membedakan antara keduanya dan melompat ke dua set instruksi yang sama sekali berbeda, tetapi itu tetap berarti Anda memiliki instruksi terpisah untuk kedua versi, hanya dengan bootstrapper yang memilih set yang benar saat runtime.


3

Dimungkinkan untuk melemparkan kembali pertanyaan ini ke lingkungan yang mungkin lebih akrab. Dengan analogi:

"Saya memiliki program Ruby yang ingin saya jalankan, tetapi platform saya hanya memiliki juru bahasa Python. Dapatkah saya menggunakan juru bahasa Python untuk menjalankan program Ruby saya, atau apakah saya harus menulis ulang program saya dengan Python?"

Arsitektur set instruksi ("target") adalah bahasa - "bahasa mesin" - dan CPU yang berbeda menerapkan bahasa yang berbeda. Jadi meminta ARM CPU untuk menjalankan biner Intel sangat mirip dengan mencoba menjalankan program Ruby menggunakan interpreter Python.


2

gcc menggunakan istilah '' arsitektur '' yang berarti '' set instruksi '' dari CPU tertentu, dan "target" mencakup kombinasi CPU dan arsitektur, bersama dengan variabel lain seperti ABI, libc, endian-ness dan banyak lagi (mungkin termasuk "bare metal"). Kompiler tipikal memiliki serangkaian kombinasi target yang terbatas (mungkin satu ABI, satu keluarga CPU, tetapi mungkin keduanya 32- dan 64-bit). Kompilator silang biasanya berarti kompiler dengan target selain sistem yang digunakannya, atau kompilator dengan banyak target atau ABI (lihat juga ini ).

Apakah binari portabel di berbagai arsitektur CPU?

Secara umum, tidak. Biner dalam istilah konvensional adalah kode objek asli untuk CPU atau keluarga CPU tertentu. Tetapi, ada beberapa kasus di mana mereka mungkin cukup portabel:

  • satu arsitektur adalah superset dari yang lain (biasanya binari x86 menargetkan i386 atau i686 daripada x86 terbaru dan terhebat, misalnya -march=core2)
  • satu arsitektur menyediakan emulasi asli atau terjemahan yang lain (Anda mungkin pernah mendengar tentang Crusoe ), atau menyediakan co-prosesor yang kompatibel (misalnya PS2 )
  • OS dan runtime mendukung multiarch (mis. kemampuan untuk menjalankan binari x86 32-bit pada x86_64), atau membuat VM / JIT mulus (Android menggunakan Dalvik atau ART )
  • ada dukungan untuk binari "gemuk" yang pada dasarnya mengandung kode duplikat untuk setiap arsitektur yang didukung

Jika Anda entah bagaimana berhasil menyelesaikan masalah ini, masalah biner portabel lainnya dari berbagai versi perpustakaan (glibc saya sedang melihat Anda) kemudian akan muncul dengan sendirinya. (Sebagian besar sistem embedded setidaknya menyelamatkan Anda dari masalah itu.)

Jika Anda belum melakukannya, sekarang adalah waktu yang tepat untuk berlari gcc -dumpspecsdan gcc --target-helpmelihat apa yang Anda hadapi.

Binari lemak memiliki berbagai kelemahan , tetapi masih memiliki potensi kegunaan ( EFI ).

Namun ada dua pertimbangan lebih lanjut yang hilang dari jawaban lain: ELF dan penerjemah ELF, dan dukungan kernel Linux untuk format biner yang sewenang-wenang . Saya tidak akan menjelaskan secara terperinci tentang binari atau bytecode untuk prosesor non-nyata di sini, meskipun dimungkinkan untuk memperlakukan ini sebagai "asli" dan mengeksekusi Java atau mengkompilasi binari bytecode Python , biner seperti itu tidak tergantung pada arsitektur perangkat keras (tetapi sebaliknya bergantung pada pada versi VM yang relevan, yang akhirnya menjalankan biner asli).

Setiap sistem Linux kontemporer akan menggunakan binari ELF (perincian teknis dalam PDF ini ), dalam kasus binari ELF dinamis, kernel bertanggung jawab untuk memuat gambar ke dalam memori tetapi ini adalah pekerjaan dari '' juru bahasa '' yang diatur dalam ELF header untuk melakukan angkat berat. Biasanya ini melibatkan memastikan semua pustaka dinamis bergantung tersedia (dengan bantuan bagian '' Dinamis '' yang mencantumkan pustaka dan beberapa struktur lain yang mencantumkan simbol yang diperlukan) - tetapi ini hampir merupakan lapisan tipuan tujuan umum.

$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses \
shared libs), stripped
$ readelf -p .interp /bin/ls
    String dump of section '.interp':
      [     0]  /lib/ld-linux.so.2

( /lib/ld-linux.so.2juga merupakan biner ELF, ia tidak memiliki juru bahasa, dan merupakan kode biner asli.)

Masalah dengan ELF adalah bahwa header dalam binary ( readelf -h /bin/ls) menandainya untuk arsitektur, kelas tertentu (32- atau 64-bit), endian-ness dan ABI (binari lemak "universal" Apple menggunakan format biner alternatif Mach-O alih-alih yang memecahkan masalah ini, ini berasal dari NextSTEP). Ini berarti bahwa executable ELF harus cocok dengan sistem yang digunakannya. Salah satu escape escape adalah interpreter, ini bisa berupa apa saja yang dapat dieksekusi (termasuk yang mengekstrak atau memetakan subbagian arsitektur spesifik dari biner aslinya dan memanggil mereka), tetapi Anda masih terkendala oleh jenis ELF yang akan diizinkan dijalankan oleh sistem Anda. . (FreeBSD memiliki cara yang menarik untuk menangani file Linux ELF , yang brandelfmemodifikasi bidang ELF ABI.)

Ada (menggunakan binfmt_misc) dukungan untuk Mach-O di linux , ada contoh di sana yang menunjukkan kepada Anda cara membuat dan menjalankan biner (32- & 64-bit) yang gemuk. Fork sumber daya / ADS , seperti yang awalnya dilakukan pada Mac, bisa menjadi solusi, tetapi tidak ada sistem file Linux asli yang mendukung ini.

Hal yang kurang lebih sama berlaku untuk modul kernel, .kofile juga ELF (meskipun mereka tidak memiliki set juru bahasa). Dalam hal ini ada lapisan tambahan yang menggunakan versi kernel ( uname -r) di jalur pencarian, sesuatu yang secara teoritis dapat dilakukan sebagai gantinya di ELF dengan versi, tetapi pada beberapa kompleksitas dan sedikit keuntungan saya curigai.

Seperti dicatat di tempat lain, Linux tidak secara alami mendukung binari lemak, tetapi ada proyek biner lemak aktif: FatELF . Sudah ada selama bertahun-tahun , tidak pernah diintegrasikan ke dalam kernel standar sebagian karena masalah paten (sekarang kedaluwarsa). Pada saat ini membutuhkan dukungan kernel dan toolchain. Itu tidak menggunakan binfmt_miscpendekatan, ini langkah-langkah header masalah ELF dan memungkinkan untuk modul kernel lemak juga.

  1. Jika saya memiliki aplikasi yang dikompilasi untuk dijalankan pada 'target x86, linux OS versi xyz', dapatkah saya menjalankan biner yang dikompilasi yang sama pada sistem lain 'target ARM, OS linux versi xyz'?

Tidak dengan ELF, itu tidak akan membiarkan Anda melakukan ini.

  1. Jika di atas tidak benar, satu-satunya cara adalah mendapatkan kode sumber aplikasi untuk membangun kembali / mengkompilasi ulang menggunakan toolchain yang relevan 'misalnya, arm-linux-gnueabi'?

Jawaban sederhananya adalah ya. (Jawaban rumit mencakup emulasi, representasi menengah, penerjemah , dan JIT; kecuali untuk kasus "penurunan versi" biner i686 untuk hanya menggunakan opcode i386, mereka mungkin tidak menarik di sini, dan perbaikan ABI berpotensi sekeras menerjemahkan kode asli. )

  1. Demikian pula, jika saya memiliki modul kernel (driver perangkat) yang dapat dimuat yang bekerja pada 'target x86, linux OS versi xyz', dapatkah saya memuat / menggunakan .ko yang dikompilasi yang sama pada sistem lain 'target ARM, OS linux versi xyz' ?

Tidak, ELF tidak akan membiarkan Anda melakukan ini.

  1. Jika di atas tidak benar, satu-satunya cara adalah mendapatkan kode sumber driver untuk membangun kembali / mengkompilasi ulang menggunakan toolchain yang relevan 'misalnya, arm-linux-gnueabi'?

Jawaban sederhananya adalah ya. Saya percaya FatELF memungkinkan Anda membangun .koyang multi-arsitektur, tetapi pada titik tertentu versi biner untuk setiap arsitektur yang didukung harus dibuat. Hal-hal yang memerlukan modul kernel sering kali datang bersama sumbernya, dan dibuat sesuai kebutuhan, mis. VirtualBox melakukan ini.

Ini sudah merupakan jawaban panjang yang mengoceh, hanya ada satu jalan memutar lagi. Kernel sudah memiliki mesin virtual bawaan, meskipun mesin khusus: BPF VM yang digunakan untuk mencocokkan paket. Filter yang dapat dibaca manusia "host foo dan bukan port 22") dikompilasi ke bytecode dan filter paket kernel menjalankannya . EBPF baru tidak hanya untuk paket, dalam teori bahwa kode VM portabel di setiap linux kontemporer, dan llvm mendukungnya tetapi untuk alasan keamanan mungkin tidak akan cocok untuk apa pun selain aturan administratif.


Sekarang, tergantung seberapa murah hati Anda dengan definisi biner yang dapat dieksekusi, Anda dapat (ab) gunakan binfmt_miscuntuk mengimplementasikan dukungan biner gemuk dengan skrip shell, dan file ZIP sebagai format wadah:

#!/bin/bash

name=$1
prog=${1/*\//}      # basename
prog=${prog/.woz/}  # remove extension
root=/mnt/tmpfs
root=$(TMPDIR= mktemp -d -p ${root} woz.XXXXXX)
shift               # drop argv[0], keep other args

arch=$(uname -m)                  # i686
uname_s=$(uname -s)               # Linux
glibc=$(getconf GNU_LIBC_VERSION) # glibc 2.17
glibc=${glibc// /-}               # s/ /-/g

# test that "foo.woz" can unzip, and test "foo" is executable
unzip -tqq "$1" && {
  unzip -q -o -j -d ${root} "$1"  "${arch}/${uname_s}/${glibc}/*" 
  test -x ${root}/$prog && ( 
    export LD_LIBRARY_PATH="${root}:${LD_LIBRARY_PATH}"
    #readlink -f "${root}/${prog}"   # for the curious
    exec -a "${name}" "${root}/${prog}" "$@" 
  )
  rc=$?
  #rm -rf -- "${root}/${prog}"       # for the brave
  exit $rc
}

Sebut ini "wozbin", dan atur dengan sesuatu seperti:

mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
printf ":%s:%s:%s:%s:%s:%s:%s" \
  "woz" "E" "" "woz" "" "/path/to/wozbin" ""  > /proc/sys/fs/binfmt_misc/register

Ini mendaftarkan .wozfile dengan kernel, wozbinskrip dipanggil sebagai gantinya dengan argumen pertama yang ditetapkan ke path .wozfile yang dipanggil .

Untuk mendapatkan file portabel (gemuk) .woz , cukup buat test.wozfile ZIP dengan hierarki direktori jadi:

i686/ 
    \- Linux/
            \- glibc-2.12/
armv6l/
    \- Linux/
            \- glibc-2.17/

Di dalam setiap direktori arch / OS / libc (pilihan sewenang-wenang) tempatkan testbiner dan komponen khusus arsitektur seperti .sofile. Ketika Anda memintanya, subdirektori yang diperlukan diekstraksi ke sistem file in-memory tmpfs (di /mnt/tmpfssini) dan dipanggil.


0

boot berry, pecahkan beberapa masalah Anda .. tetapi itu tidak menyelesaikan masalah cara berjalan di lengan hf, normall / regullAr distro linux untuk x86-32 / 64bit.

Saya pikir itu harus dibangun di dalam isolinux (boatloader linux pada usb) beberapa konverter hidup apa yang bisa mengenali distro regullar dan dalam perjalanan / konversi langsung ke hf.

Mengapa? Karena jika setiap linux dapat dikonversi dengan boot berry untuk bekerja pada arm-hf sehingga bisa membangun mekanisme boot untuk mengisolasi apa yang kita boot menggunakan untuk eacher atau dibangun di ubuntu creat start up disk.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.