Os binários são portáteis em diferentes arquiteturas de CPU?

16

Meu objetivo é ser capaz de desenvolver para Linux embarcado. Tenho experiência em sistemas embarcados usando o ARM.

Tenho algumas perguntas gerais sobre o desenvolvimento para diferentes alvos da CPU. Minhas perguntas são as seguintes:

  1. Se eu tiver um aplicativo compilado para executar em um ' destino x86, versão do SO Linux xyz ', posso executar o mesmo binário compilado em outro sistema ' destino ARM, versão do SO Linux xyz '?

  2. Se acima não for verdade, a única maneira é fazer o código-fonte do aplicativo reconstruir / recompilar usando a cadeia de ferramentas relevante 'por exemplo, arm-linux-gnueabi'?

  3. Da mesma forma, se eu tiver um módulo do kernel carregável (driver de dispositivo) que funcione em um ' destino x86, versão do sistema operacional linux xyz ', posso carregar / usar o mesmo .ko compilado em outro sistema ' destino ARM, versão do sistema operacional linux xyz ' ?

  4. Se acima não for verdade, a única maneira é fazer o código-fonte do driver reconstruir / recompilar usando a cadeia de ferramentas relevante 'por exemplo, arm-linux-gnueabi'?

idiota
fonte
27
não sim sim não
hobbs
7
Ajuda a perceber que não temos um alvo AMD e um alvo Intel, apenas um único objetivo x86 para ambos. Isso ocorre porque Intel e AMD são suficientemente compatíveis. Torna-se óbvio que o alvo do ARM existe por um motivo específico, a saber, porque os CPUs do ARM não são compatíveis com Intel / AMD / x86.
MSalters
1
Não, a menos que seja um bytecode projetado para ser executado em um ambiente de tempo de execução portátil como o Java Runtime. Se você estiver escrevendo código para uso incorporado, é provável que seu código se baseie em otimizações ou recursos específicos de processador de baixo nível e será muito difícil de portar, exigindo mais do que apenas compilação para a plataforma de destino (por exemplo, alterações no código de montagem, possivelmente reescrita vários módulos ou o programa inteiro).
bwDraco
1
@ MSalters: Na verdade, temos um objetivo da AMD: amd64, que é frequentemente rotulado como x86-64 (enquanto x86 é geralmente uma re-rotulagem de i386). Felizmente, a Intel copiou (e depois expandiu) a arquitetura AMD para que qualquer x86 de 64 bits possa executar binários amd64.
Slebetman

Respostas:

42

Não. Os binários devem ser (re) compilados para a arquitetura de destino, e o Linux não oferece nada como binários gordos prontos para uso. O motivo é que o código é compilado no código da máquina para uma arquitetura específica e o código da máquina é muito diferente entre a maioria das famílias de processadores (por exemplo, o ARM e o x86 são muito diferentes).

EDIT: vale a pena notar que algumas arquiteturas oferecem níveis de compatibilidade com versões anteriores (e ainda mais rara, compatibilidade com outras arquiteturas); em CPUs de 64 bits, é comum ter compatibilidade com versões anteriores de edições de 32 bits (mas lembre-se: suas bibliotecas dependentes também devem ser de 32 bits, incluindo sua biblioteca padrão C, a menos que você esteja vinculado estaticamente ). Também vale mencionar o Itanium , onde foi possível executar o código x86 (somente 32 bits), embora muito devagar; a baixa velocidade de execução do código x86 era pelo menos parte do motivo de não ter tido muito sucesso no mercado.

Lembre-se de que você ainda não pode usar binários compilados com instruções mais recentes em CPUs mais antigas, mesmo em modos de compatibilidade (por exemplo, você não pode usar o AVX em um binário de 32 bits nos processadores Nehalem x86 ; a CPU simplesmente não o suporta.

Observe que os módulos do kernel devem ser compilados para a arquitetura relevante; além disso, os módulos do kernel de 32 bits não funcionarão nos kernels de 64 bits ou vice-versa.

Para obter informações sobre binários de compilação cruzada (para que você não precise ter uma cadeia de ferramentas no dispositivo ARM de destino), consulte a resposta abrangente do grochmal abaixo.

Elizafox
fonte
1
Vale a pena esclarecer sobre qualquer compatibilidade (ou falta dela) entre x86 e x64, já que alguns binários x86 podem ser executados em plataformas x64. (Não estou certo de que este é o caso no Linux, mas é no Windows, por exemplo.)
jpmc26
4
@ jpmc26 é possível no Linux; mas pode ser necessário instalar primeiro as bibliotecas de compatibilidade. O suporte ao x86 é uma parte não opcional das instalações do Win64. No Linux é opcional; e como o mundo do Linux está muito mais longe ao disponibilizar versões de 64 bits de tudo o que existe, algumas distribuições não assumem o padrão de ter (todas?) bibliotecas de 32 bits instaladas. (Não tenho certeza como é comum, mas vi algumas consultas sobre a partir de pessoas correndo distros mainstreamish antes.)
Dan Neely
@ jpmc26 Atualizei minha resposta com suas anotações; Pensei em mencionar isso, mas não queria complicar a resposta.
Elizafox
16

Elizabeth Myers está correta, cada arquitetura requer um binário compilado para a arquitetura em questão. Para construir binários para uma arquitetura diferente da executada pelo sistema, você precisa de cross-compiler.


Na maioria dos casos, você precisa compilar um compilador cruzado. Eu só tenho experiência com gcc(mas acredito que llvm, e outros compiladores, tenham parâmetros semelhantes). Um gcccompilador cruzado é obtido adicionando --targetao configure:

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

Você precisa compilar gcc, glibce binutilscom estes parâmetros (e fornecer os cabeçalhos do kernel do kernel na máquina de destino).

Na prática, isso é consideravelmente mais complicado e erros de compilação diferentes aparecem em diferentes sistemas.

Existem vários guias sobre como compilar a cadeia de ferramentas GNU, mas eu recomendo o Linux From Scratch , que é mantido continuamente e faz um bom trabalho ao explicar o que os comandos apresentados fazem.

Outra opção é uma compilação de autoinicialização de um compilador cruzado. Graças à luta de compilar compiladores cruzados para diferentes arquiteturas em diferentes arquiteturas, crosstool-ngfoi criado. Ele fornece uma inicialização sobre a cadeia de ferramentas necessária para criar um compilador cruzado.

crosstool-ngsuporta vários trigêmeos de destino em diferentes arquiteturas, basicamente é um bootstrap em que as pessoas dedicam seu tempo para resolver os problemas que ocorrem durante a compilação de uma cadeia de ferramentas de compilador cruzado.


Várias distribuições fornecem compiladores cruzados como pacotes:

Em outras palavras, verifique o que sua distribuição tem disponível em termos de compiladores cruzados. Se sua distribuição não tiver um compilador cruzado para suas necessidades, você sempre poderá compilá-la.

Referências:


Nota sobre os módulos do kernel

Se você estiver compilando seu compilador cruzado manualmente, terá tudo o que precisa para compilar os módulos do kernel. Isso ocorre porque você precisa dos cabeçalhos do kernel para compilar glibc.

Porém, se você estiver usando um compilador cruzado fornecido por sua distribuição, precisará dos cabeçalhos do kernel que são executados na máquina de destino.

grochmal
fonte
FWIW O Fedora também inclui compiladores cruzados.
mattdm
@mattdm - obrigado, resposta aprimorada, acredito que tenho a parte correta do wiki do fedora vinculada.
grochmal
2
Uma maneira mais fácil do que o Linux From Scratch de obter um Linux e uma cadeia de ferramentas para outra arquitetura é crosstool-ng. Você pode adicionar isso à lista. Além disso, configurar e compilar um conjunto de ferramentas cruzadas GNU manualmente para qualquer arquitetura é incrivelmente envolvido e muito mais tedioso do que apenas --targetsinalizadores. Eu suspeito que seja parte do motivo pelo qual o LLVM está ganhando popularidade; Ele é arquitetado de tal maneira que você não precisa de uma reconstrução para atingir outra arquitetura - em vez disso, pode segmentar vários back-ends usando as mesmas bibliotecas de front-end e otimizador.
Iwillnotexist Idonotexist
@IwillnotexistIdonotexist - obrigado, alterei a resposta ainda mais. Eu nunca ouvi falar de crosstool-ng antes, e parece muito útil. Seu comentário foi realmente muito útil para mim.
grochmal
9

Observe que, como último recurso (ou seja, quando você não possui o código fonte), você pode executar binários em uma arquitetura diferente usando emuladores como qemu, dosboxou exagear. Alguns emuladores são projetados para emular sistemas diferentes do Linux (por exemplo, dosboxprojetados para executar programas do MS-DOS, e existem muitos emuladores para consoles de jogos populares). A emulação tem uma sobrecarga significativa de desempenho: os programas emulados são executados de 2 a 10 vezes mais lentos do que seus equivalentes nativos.

Se você precisar executar módulos do kernel em uma CPU não nativa, terá que emular todo o sistema operacional, incluindo o kernel da mesma arquitetura. AFAIK é impossível executar código estrangeiro dentro do kernel do Linux.

Dmitry Grigoryev
fonte
3
A penalidade de velocidade para emulação geralmente é ainda maior que 10x, mas se alguém estiver tentando executar o código escrito para uma máquina de 16Mhz em uma máquina de 4GHz (uma diferença de velocidade de 250: 1), um emulador que tenha uma penalidade de velocidade de 50: 1 ainda poderá executar código muito mais rápido do que teria sido executado na plataforma original.
supercat
7

Os binários não são apenas portáteis entre x86 e ARM, mas existem diferentes tipos de ARM .

O que você provavelmente encontrará na prática é o ARMv6 vs o ARMv7. Raspberry Pi 1 é ARMv6, versões posteriores são ARMv7. Portanto, é possível compilar código nos últimos que não funcionam no Pi 1.

Felizmente, um benefício do código aberto e do software livre é ter o código-fonte para que você possa reconstruí-lo em qualquer arquitetura. Embora isso possa exigir algum trabalho.

(O controle de versão do ARM é confuso, mas se houver um V antes do número, está falando sobre a arquitetura do conjunto de instruções (ISA). Se não houver, é um número de modelo como "Cortex M0" ou "ARM926EJS". Os números do modelo não têm nada a ver faça com os números ISA.)

pjc50
fonte
2
... e ainda existem sub-sabores diferentes para o mesmo sabor do ARM e até ABIs diferentes para o mesmo hardware (estou pensando em toda a bagunça de ponto flutuante suave / softfp / hard do ARM).
Matteo Italia
1
@MatteoItalia Ugh. As múltiplas ABIs eram um snafu, uma cura para algo pior do que a doença. Alguns ARMs não possuíam registros VFP ou NEON, outros tinham 16, outros 32. No Cortex-A8 e anteriormente, o mecanismo NEON executava uma dúzia de CCs atrás do resto do núcleo, portanto, transferir uma saída vetorial para um GPR custa um muito. O ARM começou a fazer a coisa certa - exigindo um grande subconjunto comum de recursos.
Iwillnotexist Idonotexist
7

Você sempre precisa segmentar uma plataforma. No caso mais simples, a CPU de destino executa diretamente o código compilado no binário (isso corresponde aproximadamente aos executáveis ​​COM do MS DOS). Vamos considerar duas plataformas diferentes que acabei de inventar - Armistice e Intellio. Nos dois casos, teremos um programa simples olá mundo que gera 42 na tela. Também assumirei que você está usando uma linguagem de várias plataformas de uma maneira independente de plataforma, portanto o código-fonte é o mesmo para os dois:

Print(42)

No Armistice, você tem um driver de dispositivo simples que cuida da impressão de números; portanto, tudo o que você precisa fazer é enviar para uma porta. Em nossa linguagem assembly portátil, isso corresponderia a algo assim:

out 1234h, 42

No entanto, ou o sistema Intellio não possui tal coisa, ele precisa passar por outras camadas:

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

Opa, já temos uma diferença significativa entre os dois, antes mesmo de chegarmos ao código da máquina! Isso corresponderia aproximadamente ao tipo de diferença que você tem entre Linux e MS DOS, ou um PC IBM e um X-Box (mesmo que ambos possam usar a mesma CPU).

Mas é para isso que servem os sistemas operacionais. Vamos supor que temos um HAL que garante que todas as diferentes configurações de hardware sejam tratadas da mesma maneira na camada de aplicativos - basicamente, usaremos a abordagem Intellio mesmo no Armistice, e nosso código de "montagem portátil" termina o mesmo. Isso é usado pelos sistemas modernos do tipo Unix e pelo Windows, geralmente mesmo em cenários incorporados. Bom - agora podemos ter o mesmo código de montagem verdadeiramente portátil no Armistice e Intellio. Mas e os binários?

Como assumimos, a CPU precisa executar o binário diretamente. Vejamos a primeira linha do nosso código mov a, 10h, no Intellio:

20 10

Oh. Acontece que mov a, constanté tão popular que tem sua própria instrução, com seu próprio código de operação. Como o Armistice lida com isso?

36 01 00 10

Hmm. Existe o opcode para mov.reg.imm, então precisamos de outro argumento para selecionar o registro ao qual estamos atribuindo. E a constante é sempre uma palavra de 2 bytes, na notação big endian - foi assim que o Armistice foi projetado; de fato, todas as instruções no Armistice têm 4 bytes de comprimento, sem exceções.

Agora imagine executar o binário do Intellio no Armistice: a CPU começa a decodificar a instrução, encontra o opcode 20h. No armistício, isso corresponde, digamos, à and.imm.reginstrução. Ele tenta ler a constante da palavra de 2 bytes (que 10XXjá é um problema), e depois o número do registro (outro XX). Estamos executando a instrução errada, com os argumentos errados. E pior, a próxima instrução será falsa, porque na verdade comemos outra instrução, pensando que eram dados.

O aplicativo não tem chance de funcionar e provavelmente trava ou trava quase imediatamente.

Agora, isso não significa que um executável sempre precise dizer que é executado no Intellio ou no Armistice. Você só precisa definir uma plataforma que seja independente da CPU (como bashno Unix), ou da CPU e do SO (como Java ou .NET e, atualmente, até mesmo com JavaScript). Nesse caso, o aplicativo pode usar um executável para todas as CPUs e sistemas operacionais diferentes, enquanto houver algum aplicativo ou serviço no sistema de destino (que tenha como alvo a CPU e / ou SO corretos diretamente) que traduza o código independente da plataforma em algo que CPU pode realmente executar. Isso pode ou não resultar em desempenho, custo ou capacidade.

CPUs geralmente vêm em famílias. Por exemplo, todas as CPUs da família x86 têm um conjunto comum de instruções que são codificadas exatamente da mesma maneira, para que cada CPU x86 possa executar todos os programas x86, desde que não tente usar nenhuma extensão (por exemplo, operações de ponto flutuante ou operações vetoriais). No x86, os exemplos mais comuns hoje são Intel e AMD, é claro. A Atmel é uma empresa bem conhecida que projeta CPUs na família ARM, bastante popular para dispositivos embarcados. A Apple também possui CPUs ARM próprias, por exemplo.

Mas o ARM é totalmente incompatível com o x86 - eles têm requisitos de design muito diferentes e têm muito pouco em comum. As instruções têm códigos de operação totalmente diferentes, são decodificadas de maneira diferente, os endereços de memória são tratados de maneira diferente ... Pode ser possível criar um binário que seja executado em uma CPU x86 e em uma CPU ARM, usando algumas operações seguras para distinguir entre os dois e pular para dois conjuntos de instruções completamente diferentes, mas ainda significa que você tem instruções separadas para as duas versões, com apenas um bootstrapper que escolhe o conjunto correto em tempo de execução.

Luaan
fonte
3

É possível relançar essa pergunta em um ambiente que possa ser mais familiar. Por analogia:

"Tenho um programa Ruby que desejo executar, mas minha plataforma possui apenas um intérprete Python. Posso usar o intérprete Python para executar meu programa Ruby ou preciso reescrever meu programa em Python?"

Uma arquitetura de conjunto de instruções ("destino") é uma linguagem - uma "linguagem de máquina" - e diferentes CPUs implementam idiomas diferentes. Portanto, pedir a uma CPU ARM para executar um binário Intel é como tentar executar um programa Ruby usando um interpretador Python.

Jander
fonte
2

O gcc usa os termos '' arquitetura '' para significar o '' conjunto de instruções '' de uma CPU específica, e "target" abrange a combinação de CPU e arquitetura, junto com outras variáveis, como ABI, libc, endian-ness e mais (possivelmente incluindo "bare metal"). Um compilador típico possui um conjunto limitado de combinações de destinos (provavelmente uma ABI, uma família de CPU, mas possivelmente ambas de 32 e 64 bits). Um compilador cruzado geralmente significa um compilador com um destino diferente do sistema em que ele é executado ou um com vários destinos ou ABIs (consulte também isso ).

Os binários são portáteis em diferentes arquiteturas de CPU?

Em geral, não. Um binário em termos convencionais é o código de objeto nativo para uma CPU ou família de CPU específica. Mas há vários casos em que eles podem ser moderadamente a altamente portáteis:

  • uma arquitetura é um superconjunto de outra (normalmente os binários x86 têm como alvo i386 ou i686 em vez do x86 mais recente e melhor, por exemplo -march=core2)
  • uma arquitetura fornece emulação nativa ou tradução de outra (você pode ter ouvido falar de Crusoe ) ou fornece coprocessadores compatíveis (por exemplo, PS2 )
  • o sistema operacional e o tempo de execução oferecem suporte a multiarch (por exemplo, capacidade de executar binários x86 de 32 bits no x86_64) ou tornar a VM / JIT integrada (Android usando Dalvik ou ART )
  • existe suporte para binários "gordos" que contêm essencialmente código duplicado para cada arquitetura suportada

Se você, de alguma maneira, conseguir resolver esse problema, o outro problema binário portátil das inúmeras versões da biblioteca (glibc eu estou olhando para você) se apresentará. (A maioria dos sistemas embarcados evita esse problema em particular.)

Se você ainda não o fez, agora é uma boa hora para correr gcc -dumpspecs e gcc --target-helpver o que você está enfrentando.

Binários gordos têm várias desvantagens , mas ainda têm usos potenciais ( EFI ).

Há duas considerações adicionais ausentes nas outras respostas: o ELF e o interpretador ELF e o suporte do kernel Linux para formatos binários arbitrários . Não entrarei em detalhes sobre binários ou bytecode para processadores não reais aqui, embora seja possível tratá-los como "nativos" e executar binários Java ou Python bytecode compilados , esses binários são independentes da arquitetura de hardware (mas dependem na versão da VM relevante, que finalmente executa um binário nativo).

Qualquer sistema Linux contemporâneo usará binários ELF (detalhes técnicos neste PDF ); no caso de binários dinâmicos ELF, o kernel é responsável por carregar a imagem na memória, mas é o trabalho do '' intérprete '' definido no ELF cabeçalhos para fazer o trabalho pesado. Normalmente, isso envolve garantir que todas as bibliotecas dinâmicas dependentes estejam disponíveis (com a ajuda da seção '' Dinâmico '', que lista as bibliotecas e algumas outras estruturas que listam os símbolos necessários) - mas essa é quase uma camada indireta de uso geral.

$ 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.2também é um binário ELF, não possui um intérprete e é um código binário nativo.)

O problema com o ELF é que o cabeçalho no binário ( readelf -h /bin/ls) o marca para uma arquitetura específica, classe (32 ou 64 bits), endian-ness e ABI (binários de gordura "universais" da Apple) usam um formato binário alternativo Mach-O em vez disso, que resolve esse problema, ele se originou no NextSTEP). Isso significa que um executável ELF deve corresponder ao sistema no qual ele deve ser executado. Uma saída de escape é o intérprete, que pode ser qualquer executável (incluindo um que extrai ou mapeia subseções específicas da arquitetura do binário original e as invoca), mas você ainda está limitado pelo (s) tipo (s) de ELF que seu sistema permitirá executar . (O FreeBSD possui uma maneira interessante de lidar com arquivos Linux ELF , brandelfmodificando o campo ELF ABI.)

Existe (usando binfmt_misc) suporte para Mach-O no Linux , há um exemplo que mostra como criar e executar um binário gordo (32 e 64 bits).Garfos de recursos / ADS , como originalmente feito no Mac, podem ser uma solução alternativa, mas nenhum sistema de arquivos Linux nativo suporta isso.

Mais ou menos a mesma coisa se aplica aos módulos do kernel, .ko arquivos também são ELF (embora não tenham nenhum conjunto de intérpretes). Nesse caso, há uma camada extra que usa a versão do kernel ( uname -r) no caminho de pesquisa, algo que teoricamente poderia ser feito em ELF com versionamento, mas com alguma complexidade e pouco ganho, suspeito.

Como observado em outro lugar, o Linux não suporta nativamente binários de gordura, mas há um projeto ativo de binários de gordura: FatELF . Já existe há anos , nunca foi integrado ao kernel padrão em parte devido a preocupações de patente (agora expiradas). No momento, ele requer suporte ao kernel e ao conjunto de ferramentas. Ele não usa a binfmt_miscabordagem, isso evita problemas no cabeçalho do ELF e também permite módulos de kernel gordo.

  1. Se eu tiver um aplicativo compilado para executar em um 'destino x86, versão do SO Linux xyz', posso executar o mesmo binário compilado em outro sistema 'destino ARM, versão do SO Linux xyz'?

Não com o ELF, ele não permitirá que você faça isso.

  1. Se acima não for verdade, a única maneira é fazer o código-fonte do aplicativo reconstruir / recompilar usando a cadeia de ferramentas relevante 'por exemplo, arm-linux-gnueabi'?

A resposta simples é sim. (As respostas complicadas incluem emulação, representações intermediárias, tradutores e JIT; exceto no caso de "rebaixar" um binário i686 para usar apenas os códigos opcionais i386, eles provavelmente não são interessantes aqui, e os consertos da ABI são potencialmente tão difíceis quanto traduzir código nativo. )

  1. Da mesma forma, se eu tiver um módulo do kernel carregável (driver de dispositivo) que funcione em um 'destino x86, versão do sistema operacional linux xyz', posso carregar / usar o mesmo .ko compilado em outro sistema 'destino ARM, versão do sistema operacional linux xyz' ?

Não, a ELF não permitirá que você faça isso.

  1. Se acima não for verdade, a única maneira é fazer o código-fonte do driver reconstruir / recompilar usando a cadeia de ferramentas relevante 'por exemplo, arm-linux-gnueabi'?

A resposta simples é sim. Acredito que o FatELF permite criar uma .koarquitetura que é multi-arquitetura, mas em algum momento uma versão binária para cada arquitetura suportada deve ser criada. Coisas que requerem módulos do kernel geralmente vêm com a fonte e são construídas conforme necessário, por exemplo, o VirtualBox faz isso.

Esta já é uma resposta longa, apenas um desvio. O kernel possui uma máquina virtual embutida, embora dedicada: a VM BPF, que é usada para corresponder aos pacotes. O filtro legível por humanos "host foo e não a porta 22") é compilado em um bytecode e o filtro de pacotes do kernel o executa . O novo eBPF não é apenas para pacotes, na teoria de que o código da VM é portátil em qualquer linux contemporâneo, e o llvm o suporta, mas por razões de segurança, provavelmente não será adequado para nada além de regras administrativas.


Agora, dependendo de sua generosidade com a definição de um executável binário, você pode (ab) usar binfmt_miscpara implementar suporte binário gordo com um script de shell e arquivos ZIP como um formato de contêiner:

#!/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
}

Chame isso de "wozbin" e configure-o com algo como:

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

Isso registra os .wozarquivos com o kernel; o wozbinscript é chamado em vez disso, com seu primeiro argumento definido no caminho de um .wozarquivo invocado .

Para obter um .woz arquivo portátil (gordo) , basta criar um test.wozarquivo ZIP com uma hierarquia de diretórios para:

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

Em cada diretório arch / OS / libc (uma escolha arbitrária), coloque o testbinário e os componentes específicos da arquitetura , como .soarquivos. Quando você o invoca, o subdiretório necessário é extraído para um sistema de arquivos em memória tmpfs ( /mnt/tmpfsaqui) e invocado.

mr.spuratic
fonte
0

baga bota, resolver alguns dos seus problemas .. mas não resolver novamente o problema de como executar no braço hf, normall / regullAr linux distro para x86-32 / 64bit.

Eu acho que deve ser embutido no isolinux (boatloader linux on usb) algum conversor ao vivo que possa reconhecer distro regular e em passeio / conversão ao vivo para hf.

Por quê? Porque se cada linux puder ser convertido por berry boot para trabalhar no arm-hf, ele poderá criar um mecanismo de inicialização do bery para isolinux o que inicializamos usando para cada exemplo ou disco de inicialização do ubuntu creat.

fdf
fonte