AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 420513
Accepted
JCDeen
JCDeen
Asked: 2018-01-30 12:47:47 +0800 CST2018-01-30 12:47:47 +0800 CST 2018-01-30 12:47:47 +0800 CST

Um executável do Linux compilado em um "sabor" do Linux será executado em um diferente?

  • 772

O executável de um programa pequeno e extremamente simples, como o mostrado abaixo, compilado em um tipo de Linux, será executado em um tipo diferente? Ou precisaria ser recompilado?

A arquitetura da máquina importa em um caso como este?

int main()
{
  return (99);
}
linux compiling
  • 6 6 respostas
  • 23721 Views

6 respostas

  • Voted
  1. DopeGhoti
    2018-01-30T13:24:08+08:002018-01-30T13:24:08+08:00

    Resumindo: se você estiver levando um binário compilado de um host para outro usando a mesma arquitetura (ou uma compatível) , você pode perfeitamente levá-lo para outra distribuição . No entanto, à medida que a complexidade do código aumenta, a probabilidade de ser vinculado a uma biblioteca que não está instalada; instalado em outro local; ou instalado em uma versão diferente, aumenta. Tomando por exemplo o seu código, para o qual lddrelata as seguintes dependências quando compilado gcc -o exit-test exit-test.cem um host Ubuntu Linux (derivado do Debian):

    $ ldd exit-test
        linux-gate.so.1 =>  (0xb7748000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb757b000)
        /lib/ld-linux.so.2 (0x8005a000)
    

    Obviamente, este binário não será executado se eu o transferir para, digamos, um Mac ( ./exit-test: cannot execute binary file: Exec format error). Vamos tentar movê-lo para uma caixa RHEL:

    $ ./exit-test
    -bash: ./exit-test: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
    

    Oh céus. Por que isso pode ser?

    $ ls /lib/ld-l* # reference the `ldd` output above
    ls: cannot access /lib/ld-l*: No such file or directory
    

    Mesmo para este caso de uso, o empilhamento falhou devido à falta de bibliotecas compartilhadas.

    No entanto, se eu compilá-lo com gcc -static exit-test-static exit-test.c, portá-lo para o sistema sem as bibliotecas funcionará bem. À custa, é claro, do espaço em disco:

    $ ls -l ./exit-test{,-static}
    -rwxr-xr-x  1 username  groupname    7312 Jan 29 14:18 ./exit-test
    -rwxr-xr-x  1 username  groupname  728228 Jan 29 14:27 ./exit-test-static
    

    Outra solução viável seria instalar as bibliotecas necessárias no novo host.

    Tal como acontece com muitas coisas no universo U&L, este é um gato com muitas peles, duas das quais são descritas acima.

    • 74
  2. Best Answer
    thrig
    2018-01-30T13:13:14+08:002018-01-30T13:13:14+08:00

    Depende. Algo compilado para IA-32 (Intel 32 bits) pode ser executado em amd64, pois o Linux em Intel mantém a compatibilidade com aplicativos de 32 bits (com software adequado instalado). Aqui está o codecompilado no sistema RedHat 7.3 de 32 bits (por volta de 2002, gcc versão 2.96) e, em seguida, o binário copiado e executado em um sistema Centos 7.4 de 64 bits (por volta de 2017):

    -bash-4.2$ file code
    code: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
    -bash-4.2$ ./code
    -bash: ./code: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
    -bash-4.2$ sudo yum -y install glibc.i686
    ...
    -bash-4.2$ ./code ; echo $?
    99
    

    O antigo RedHat 7.3 para Centos 7.4 (essencialmente RedHat Enterprise Linux 7.4) permanece na mesma família de "distribuição", então provavelmente terá melhor portabilidade do que ir de uma instalação aleatória "Linux do zero" de 2002 para alguma outra distribuição Linux aleatória em 2018 .

    Algo compilado para amd64 não funcionaria apenas em versões de 32 bits do Linux (o hardware antigo não conhece o novo hardware). Isso também é verdade para novos softwares compilados em sistemas modernos destinados a serem executados em coisas antigas, pois bibliotecas e até mesmo chamadas de sistema podem não ser portáteis para trás, portanto, podem exigir truques de compilação ou obter um compilador antigo e assim por diante, ou possivelmente em vez disso compilando no sistema antigo. (Esta é uma boa razão para manter as máquinas virtuais de coisas antigas por perto.)

    A arquitetura importa; amd64 (ou IA-32) é muito diferente de ARM ou MIPS, portanto, não se espera que o binário de um deles seja executado em outro. No nível de montagem, a mainseção do seu código em IA-32 compila via gcc -S code.cpara

    main:
        pushl %ebp
        movl %esp,%ebp
        movl $99,%eax
        popl %ebp
        ret
    

    com o qual um sistema amd64 pode lidar (em um sistema Linux - o OpenBSD, ao contrário do amd64 , não suporta binários de 32 bits; a compatibilidade com versões anteriores com archs antigos oferece espaço de manobra aos invasores, por exemplo, CVE-2014-8866 e amigos). Enquanto isso, em um sistema MIPS big-endian, main ele compila para:

    main:
            .frame  $fp,8,$31
            .mask   0x40000000,-4
            .fmask  0x00000000,0
            .set    noreorder
            .set    nomacro
            addiu   $sp,$sp,-8
            sw      $fp,4($sp)
            move    $fp,$sp
            li      $2,99
            move    $sp,$fp
            lw      $fp,4($sp)
            addiu   $sp,$sp,8
            j       $31
            nop
    

    com o qual um processador Intel não terá ideia do que fazer e, da mesma forma, para o conjunto Intel no MIPS.

    Você poderia usar QEMU ou algum outro emulador para executar código estrangeiro (talvez muito, muito lentamente).

    No entanto! Seu código é um código muito simples, então terá menos problemas de portabilidade do que qualquer outra coisa; os programas normalmente fazem uso de bibliotecas que foram alteradas ao longo do tempo (glibc, openssl, ...); para aqueles, também pode ser necessário instalar versões mais antigas de várias bibliotecas (RedHat, por exemplo, normalmente coloca "compat" em algum lugar no nome do pacote para tal)

    compat-glibc.x86_64                     1:2.12-4.el7.centos
    

    ou possivelmente se preocupe com alterações de ABI (Application Binary Interface) para coisas muito antigas que usam glibc ou alterações mais recentes devido a C++ 11 ou outras versões de C++. Pode-se também compilar estático (aumentando muito o tamanho do binário no disco) para tentar evitar problemas de biblioteca, embora algum binário antigo faça isso depende se a distribuição Linux antiga estava compilando quase tudo dinâmico (RedHat: sim) ou não. Por outro lado, coisas como patchelfpodem reajustar binários dinâmicos (ELF, mas provavelmente não a.outformatar) para usar outras bibliotecas.

    No entanto! Ser capaz de executar um programa é uma coisa e realmente fazer algo útil com ele é outra. Antigos binários Intel de 32 bits podem ter problemas de segurança se dependerem de uma versão do OpenSSL que tenha algum problema de segurança horrível e sem suporte, ou o programa pode não ser capaz de negociar com servidores web modernos (como o moderno os servidores rejeitam os antigos protocolos e cifras do antigo programa), ou a versão 1 do protocolo SSH não é mais suportada, ou ...

    • 51
  3. Rui F Ribeiro
    2018-01-30T13:21:25+08:002018-01-30T13:21:25+08:00

    Somando-se às excelentes respostas de @thrig e @DopeGhoti: sistemas operacionais Unix ou semelhantes a Unix, incluindo Linux, sempre foram tradicionalmente projetados e alinhados mais para a portabilidade do código-fonte do que binários.

    Se não tiver nada específico de hardware ou ser uma fonte simples como no seu exemplo, você pode movê-lo sem nenhum problema entre praticamente qualquer versão do Linux ou arquitetura como código-fonte , desde que os servidores de destino tenham os pacotes de desenvolvimento C instalados , as bibliotecas necessárias e as bibliotecas de desenvolvimento correspondentes instaladas.

    No que diz respeito à portabilidade de código mais avançado de versões mais antigas do Linux distantes no tempo, ou programas mais específicos, como módulos do kernel para diferentes versões do kernel, você pode ter que adaptar e modificar o código-fonte para levar em consideração bibliotecas/APIs/ABIs obsoletos.

    • 25
  4. bta
    2018-01-30T15:37:14+08:002018-01-30T15:37:14+08:00

    Por padrão , você quase certamente terá problemas com bibliotecas externas. Algumas das outras respostas dão mais detalhes sobre esses problemas, então não vou duplicar o trabalho deles.

    Você pode , no entanto, compilar muitos programas - mesmo os não triviais - para serem portáveis ​​entre sistemas Linux. A chave é um kit de ferramentas chamado Linux Standard Base . O LSB foi projetado para criar exatamente esses tipos de aplicativos portáteis. Compile um aplicativo para LSB v5.0 e ele será executado em qualquer outro ambiente Linux (da mesma arquitetura) que implemente LSB v5.0. Algumas distribuições Linux são compatíveis com LSB e outras incluem kits de ferramentas/bibliotecas LSB como um pacote instalável. Se você criar seu aplicativo usando as ferramentas LSB (como o lsbccwrapper para gcc) e vincular à versão LSB das bibliotecas, criará um aplicativo portátil.

    • 22
  5. plugwash
    2018-01-31T06:35:08+08:002018-01-31T06:35:08+08:00

    Pode ser.

    Coisas que tendem a quebrá-lo incluem.

    1. Diferentes arquiteturas. Obviamente, arquiteturas totalmente diferentes não funcionarão (a menos que você tenha algo como modo de usuário qemu com binfmt_misc, mas isso dificilmente é uma configuração normal). Os binários x86 podem funcionar no amd64, mas apenas se as bibliotecas de 32 bits necessárias estiverem disponíveis.
    2. Versões da biblioteca. Se a soversion estiver errada, ela não encontrará a biblioteca. Se a soversion for a mesma, mas o binário for construído em uma versão mais recente da biblioteca em relação à qual está sendo executado, poderá falhar ao carregar devido a novos símbolos ou novas versões de símbolos. Em particular, a glibc é uma usuária intensiva de versionamento de símbolos, portanto, os binários construídos em uma glibc mais recente têm grande probabilidade de falhar com uma glibc mais antiga.

    Se você evitar o uso de bibliotecas que mudam rapidamente, evitar mudanças de arquitetura e construir na distro mais antiga que deseja atingir, terá uma boa chance de fazer um binário funcionar em muitas distros.

    • 11
  6. Ben
    2018-02-02T04:55:06+08:002018-02-02T04:55:06+08:00

    Além de algumas das coisas mencionadas anteriormente, houve algumas alterações no formato do arquivo executável. Na maioria das vezes, o Linux usa ELF, mas as versões mais antigas usavam a.out ou COFF.

    O início de um wikihole:

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

    Pode haver uma maneira de obter versões mais antigas para executar formatos mais novos, mas eu pessoalmente nunca examinei isso.

    • 5

relate perguntas

  • Inicie/pare o serviço systemd usando o atalho de teclado [fechado]

  • O OpenVPN auto-compilado não inicia a partir do systemd

  • Necessidade de algumas chamadas de sistema

  • astyle não altera a formatação do arquivo de origem

  • Passe o sistema de arquivos raiz por rótulo para o kernel do Linux

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve