Pergunta

Estamos usando um compilador legado, baseado no gcc 2.6.0, para compilação cruzada para um processador embutido antigo que ainda usamos (sim, ainda está em uso desde 1994!).O engenheiro que fez a porta gcc para este chip já mudou há muito tempo.Embora possamos recuperar a fonte do GCC 2.6.0 de algum lugar da Web, o conjunto de alterações para este chip desapareceu nos corredores da história corporativa.Nós nos atrapalhamos até recentemente, pois o compilador ainda rodava e produzia executáveis ​​viáveis, mas a partir do kernel Linux 2.6.25 (e também 2.6.26) ele falha com a mensagem gcc: virtual memory exhausted...mesmo quando executado sem parâmetros ou apenas com -v.Reinicializei meu sistema de desenvolvimento (de 2.6.26) usando o kernel 2.6.24 e o compilador funciona novamente (reinicializar com 2.6.25 não).

Temos um sistema que mantemos em 2.6.24 apenas com o propósito de fazer compilações para este chip, mas estamos nos sentindo um pouco expostos caso o mundo Linux avance a ponto de não podermos mais reconstruir um sistema que funcione o compilador (ou seja,nosso sistema 2.6.24 morre e não conseguimos instalar e executar o 2.6.24 em um novo sistema porque algumas partes do software não estão mais disponíveis).

Alguém tem alguma idéia do que poderíamos fazer em uma instalação mais moderna para executar esse compilador legado?

Editar:

Respondendo a alguns comentários...

Infelizmente, são as alterações no código-fonte específicas do nosso chip que são perdidas.Essa perda ocorreu em duas grandes reorganizações de empresas e vários administradores de sistemas (alguns dos quais realmente deixaram uma bagunça).Agora usamos o controle de configuração, mas isso significa fechar a porta do celeiro tarde demais para esse problema.

O uso de uma VM é uma boa ideia e pode ser o que acabaremos fazendo.Obrigado por essa ideia.

Finalmente, tentei strace conforme sugerido pelo ephemient e descobri que a última chamada do sistema foi brk() que retornou um erro no novo sistema (kernel 2.6.26) e retornou sucesso no sistema antigo (kernel 2.6.24).Isso indicaria que realmente estou ficando sem memória virtual, exceto que tcsh "limit" retorna os mesmos valores em sistemas antigos e novos, e /proc/meminfo mostra que os novos sistemas têm um pouco mais de memória e um pouco mais de espaço de troca.Talvez seja um problema de fragmentação ou de onde o programa está sendo carregado?

Eu fiz mais algumas pesquisas e a "randomização brk" foi adicionada no kernel 2.6.25, no entanto CONFIG_COMPAT_BRK é supostamente habilitado por padrão (o que desativa a randomização brk).

Editar:

OK, mais informações:Realmente parece que a randomização brk é a culpada, o gcc legado está chamando brk() para alterar o final do segmento de dados e agora falha, fazendo com que o gcc legado relate "memória virtual esgotada".Existem algumas maneiras documentadas de desabilitar a randomização do brk:

  • sudo echo 0 > /proc/sys/kernel/randomize_va_space

  • sudo sysctl -w kernel.randomize_va_space=0

  • iniciando um novo shell com setarch i386 -R tcsh (ou "-R -L")

Eu os experimentei e eles parecem ter um efeito no sentido de que o valor de retorno do brk() é diferente (e sempre o mesmo) do que sem eles (tentei no kernel 2.6.25 e 2.6.26), mas o brk() ainda falha, então o gcc legado ainda falha :-(.

Além disso eu configurei vm.legacy_va_layout=1 e vm.overcommit_memory=2 sem alterações, e eu reiniciei com o vm.legacy_va_layout=1 e kernel.randomize_va_space=0 configurações salvas em /etc/sysctl.conf.Ainda não há mudança.

Editar:

Usando kernel.randomize_va_space=0 no kernel 2.6.26 (e 2.6.25) resulta na seguinte chamada brk() sendo relatada por strace legacy-gcc:

brk(0x80556d4) = 0x8056000

Isso indica que brk() falhou, mas parece que falhou porque o segmento de dados já termina além do que foi solicitado.Usando objdump, posso ver que o segmento de dados deve terminar em 0x805518c, enquanto o brk() com falha indica que o segmento de dados atualmente termina em 0x8056000:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000013  080480d4  080480d4  000000d4  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .hash         000001a0  080480e8  080480e8  000000e8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .dynsym       00000410  08048288  08048288  00000288  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .dynstr       0000020e  08048698  08048698  00000698  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .rel.bss      00000038  080488a8  080488a8  000008a8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .rel.plt      00000158  080488e0  080488e0  000008e0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .init         00000008  08048a40  08048a40  00000a40  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  7 .plt          000002c0  08048a48  08048a48  00000a48  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  8 .text         000086cc  08048d10  08048d10  00000d10  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  9 .fini         00000008  080513e0  080513e0  000093e0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 10 .rodata       000027d0  080513e8  080513e8  000093e8  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 11 .data         000005d4  08054bb8  08054bb8  0000bbb8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 12 .ctors        00000008  0805518c  0805518c  0000c18c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 13 .dtors        00000008  08055194  08055194  0000c194  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 14 .got          000000b8  0805519c  0805519c  0000c19c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 15 .dynamic      00000088  08055254  08055254  0000c254  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 16 .bss          000003b8  080552dc  080552dc  0000c2dc  2**3
                  ALLOC
 17 .note         00000064  00000000  00000000  0000c2dc  2**0
                  CONTENTS, READONLY
 18 .comment      00000062  00000000  00000000  0000c340  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
no symbols

Editar:

Para ecoar o comentário do efemiente abaixo:“Tão estranho tratar o GCC como um binário sem fonte”!

Portanto, usando strace, objdump, gdb e meu conhecimento limitado de assembler e arquitetura 386, rastreei o problema até a primeira chamada de malloc no código legado.O gcc legado chama malloc, que retorna NULL, o que resulta na mensagem "memória virtual esgotada" no stderr.Este malloc está em libc.so.5, e chama Getenv várias vezes e acaba chamando Brk () ...Acho que para aumentar a pilha ...que falha.

A partir disso, só posso supor que o problema é mais do que a randomização do brk, ou não desativei totalmente a randomização do brk, apesar das configurações de sysctl randomize_va_space=0 e legado_va_layout=1.

Foi útil?

Solução

Instale o linux + o antigo gcc em uma máquina virtual.

Outras dicas

Você tem o fontes para este compilador personalizado?Se você puder recuperar a linha de base 2.6.0 (e isso deve ser relativamente fácil), então diff e patch deverão recuperar seu conjunto de alterações.

O que eu recomendo é usar esse conjunto de alterações para criar uma nova versão em relação ao gcc atualizado.E ENTÃO COLOQUE-O SOB CONTROLE DE CONFIGURAÇÃO.

Desculpe, não quero gritar.É que venho dizendo a mesma coisa há quase 30 anos.

Você pode strace o gcc-2.6.0 executável?Pode estar fazendo algo como ler /proc/$$/maps, e ficar confuso quando a saída muda de maneira insignificante.Um problema semelhante foi notei recentemente entre 2.6.28 e 2.6.29.

Se sim, você pode hackear /usr/src/linux/fs/proc/task_mmu.c ou algo próximo para restaurar a saída antiga ou configurar algum $LD_PRELOAD fingir gcc em ler outro arquivo.

Editar

Desde que você mencionou brk...

CONFIG_COMPAT_BRK faz o padrão kernel.randomize_va_space=1 em vez de 2, mas isso ainda randomiza tudo, exceto o heap (brk).

Veja se o seu problema desaparece se você echo 0 > /proc/sys/kernel/randomize_va_space ou sysctl kernel.randomize_va_space=0 (equivalente).

Se sim, adicione kernel.randomize_va_space = 0 para /etc/sysctl.conf ou adicione norandmaps para a linha de comando do kernel (equivalente) e seja feliz novamente.

eu me deparei esse e pensei sobre o seu problema.Talvez você encontre uma maneira de brincar com o binário para movê-lo para o formato ELF?Ou pode ser irrelevante, mas brincar com o objdump pode fornecer mais informações.

Você pode dar uma olhada no mapa de memória do processo?

Então eu resolvi algo...não é uma solução completa, mas supera o problema original que tive com o gcc legado.

Colocando pontos de interrupção em cada chamada libc no .plt (tabela de ligação de procedimentos), vejo que malloc (em libc.so.5) chama getenv() para obter:

    MALLOC_TRIM_THRESHOLD_
    MALLOC_TOP_PAD_
    MALLOC_MMAP_THRESHOLD_
    MALLOC_MMAP_MAX_
    MALLOC_CHECK_

Então eu pesquisei isso na web e encontrei esse que aconselhou

    setenv MALLOC_TOP_PAD_ 536870912

então o legado gcc FUNCIONA!!!!

Mas não é gratuito, ele atingiu o link na compilação antes de falhar, então há algo mais acontecendo com o nld legado que temos :-( Está relatando:

    Virtual memory exceeded in `new'

Em /etc/sysctl.conf eu tenho:

    kernel.randomize_va_space=0
    vm.legacy_va_layout=1

Ainda funciona da mesma forma se

    kernel.randomize_va_space=1
    vm.legacy_va_layout=0

mas não se

kernel.randomize_va_space=2

Houve uma sugestão de usar "ldd" para ver as dependências da biblioteca compartilhada:O Legacy GCC precisa apenas de libc5, mas o NLD legado também precisa de libg ++. So.27, libstdc ++. ??) e e quanto a libc5-compat?

Então, como eu disse, ainda não estou livre para casa...estar se aproximando.Provavelmente postarei uma nova pergunta sobre o problema do nld.

Editar:

Originalmente, eu iria me abster de "Aceitar" esta resposta, pois ainda tenho um problema com o vinculador legado correspondente, mas para obter pelo menos alguma finalidade nesta questão, estou repensando essa posição.

Os agradecimentos vão para:

  • an0nym0usc0ward pela sugestão de usar uma VM (que pode eventualmente se tornar a resposta aceita)
  • efemiente por sugerir o uso de strace e ajuda com o uso de stackoverflow
  • shodanex por sugerir o uso de objdump

Editar

Abaixo estão as últimas coisas que aprendi, e agora aceitarei a solução VM já que não consegui resolver totalmente de outra forma (pelo menos no tempo previsto para isso).

Os kernels mais novos têm um sinalizador de construção CONFIG_COMPAT_BRK para permitir que libc5 seja usado, então, presumivelmente, construir um novo kernel com este sinalizador resolverá o problema (e olhando através do kernel src, parece que sim, mas não posso ter certeza, já que fiz isso não seguir todos os caminhos).Há também outra maneira documentada de permitir o uso da libc5 em tempo de execução (em vez de em tempo de construção do kernel):sudo sysctl -w kernel.randomize_va_space=0.Isso, no entanto, não faz um trabalho completo e alguns (a maioria?) Aplicativos libc5 ainda quebrarão, por exemplo,nosso compilador e vinculador legado.Isto parece ser devido a uma diferença nas suposições de alinhamento entre os kernels mais novos e mais antigos.Eu corrigi o binário do vinculador para fazê-lo pensar que tem uma seção bss maior, a fim de trazer o final do bss até um limite de página, e isso funciona no kernel mais recente quando o sysctl var kernel.randomize_va_space=0.Esta NÃO é uma solução satisfatória para mim, já que estou corrigindo cegamente um executável binário crítico e, embora a execução do vinculador corrigido no kernel mais recente tenha produzido uma saída idêntica em bits ao vinculador original executado no kernel mais antigo, isso não prova que alguma outra entrada do vinculador (ou seja,mudarmos o programa que está sendo vinculado) também produzirá resultados idênticos.

Você não poderia simplesmente criar uma imagem de disco que possa ser reinstalada se o sistema falhar?ou fazer uma VM?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top