Pergunta

Estou produzindo um arquivo hex para rodar em um processador ARM que eu quero manter abaixo 32K. É actualmente muito maior do que isso e eu me perguntava se alguém pode ter alguns conselhos sobre qual é a melhor abordagem para slim-lo?

Aqui está o que eu fiz até agora

  1. Então eu corro já 'size' sobre ele para determinar o quão grande o arquivo hex é.
  2. Em seguida, 'tamanho' novamente para ver o quão grande cada um dos arquivos de objetos são que apontam para criar os arquivos hexadecimais. Parece que a maioria do tamanho vem de bibliotecas externas.
  3. Então eu usei 'readelf' para ver quais as funções ocupam mais memória.
  4. Eu procurei através do código para ver se eu poderia eliminar as chamadas para essas funções.

Aqui é onde eu ficar preso, há algumas funções que eu não chamar diretamente (por exemplo _vfprintf) e não consigo encontrar o que chama para que eu possa remover a chamada (como eu acho que não precisa dele).

Então, quais são os próximos passos?

Response to respostas:

  • Como pode ver, existem funções que está sendo chamado que ocupam muita memória. Não pode, contudo, encontrar o que está chamando.
  • Eu quero omitir essas funções (se possível), mas não consigo encontrar o que está chamando-os! Poderia ser chamado de qualquer número de funções de biblioteca, eu acho.
  • O vinculador está funcionando como desejado, penso eu, que só inclui os arquivos de biblioteca relevantes. Como você sabe se apenas as funções relevantes estão sendo incluídos? Você pode definir uma bandeira ou algo para isso?
  • Eu estou usando GCC
Foi útil?

Solução

Lista Geral:

  • Certifique-se de que você tem as opções de depuração compilador e vinculador desativada
  • compilar e linkar com todas as opções de tamanho ligado (-Os em gcc)
  • Executar strip no executável
  • Gerar um arquivo de mapa e verificar seus tamanhos de função. Você pode obter o seu vinculador para gerar o arquivo de mapa (-M ao usar ld), ou você pode usar objdump no executável final (Note que isto irá funcionar apenas em um executável unstripped!) Isso não vai realmente resolver o problema, mas ele vai deixar você saber dos piores criminosos.
  • Use nm para investigar símbolos que são chamadas de cada um dos seus arquivos de objeto. Isso deve ajudar a encontrar funções que está chamando que você não quer que seja chamado.

Na pergunta original era uma sub-questão sobre a inclusão de funções só relevantes. gcc irá incluir todas as funções dentro de cada arquivo objeto que é usado. Para colocar isso de outra forma, se você tem um arquivo de objeto que contém 10 funções, todas as 10 funções estão incluídos no seu mesmo executável se um 1 é realmente chamado.

As bibliotecas padrão (ex. Libc) irá dividir funções em muitos arquivos de objetos separados, que depois são arquivados. O executável é então ligado contra o arquivo. Se dividindo em muitos arquivos objeto o ligador é capaz de incluir apenas as funções que são realmente chamados. (Isso pressupõe que você está ligando estaticamente)

Não há nenhuma razão para que você não pode fazer o mesmo truque. Claro, você poderia argumentar que se as funções não são chamados a provavelmente você pode removê-los você mesmo.

Se você está ligando estaticamente contra outras bibliotecas que você pode executar as ferramentas listadas acima sobre eles também se certificar de que eles estão seguindo as regras semelhantes.

Outras dicas

Outra otimização que pode poupar-lhe trabalho é -ffunction-seções, -Wl, - GC-seções, supondo que você está usando o GCC. Um bom conjunto de ferramentas não precisam ser informados de que, apesar de tudo.

Explicação: GNU ligações ld seções, e GCC emite uma seção por unidade de tradução menos que você diga o contrário. Mas, em C ++, os nós no gráfico ser dependente são objetos e funções.

Apenas para checar e documento para referência futura, mas você usa instruções Thumb? Eles são 16 versões das instruções normais bits. Às vezes você pode precisar de 2 16 instruções bit, por isso não vai economizar 50% no espaço de código.

A vinculador decente deve levar apenas as funções necessárias. No entanto, você pode precisar de configurações do compilador & Linke empacotar funções de ligação individual.

Em projetos profundamente enraizadas Eu sempre tento evitar o uso de quaisquer funções da biblioteca padrão. Mesmo funções simples, como "strtol ()" explodir o tamanho do binário. Se possível simplesmente evitar essas chamadas.

Na maioria dos projetos profundamente enraizadas que você não precisa de um versátil "printf ()" ou alocação de memória dinâmica (muitos controladores têm 32kb ou menos RAM).

Em vez de usar apenas "printf ()" Eu uso um costume "printf ()" muito simples, esta função só pode imprimir números em formato hexadecimal ou decimal não mais. A maioria das estruturas de dados são pré-alocados em tempo de compilação.

Ok, então, no final, eu só reduziu o projecto para a forma mais simples, de, arquivos, em seguida, adicionados lentamente um por um até que a função que eu queria remover apareceu no arquivo 'readelf'. Então, quando eu tinha o arquivo eu comentei tudo para fora e lentamente adicionar coisas de volta até a função apareceu novamente. Então, no final eu descobri o que chamou de e removeu todas essas chamadas ... Agora ele funciona como desejado ... doce!

Deve haver uma maneira melhor de fazê-lo embora.

Andrew Edgecombe tem uma grande lista, mas se você realmente quer para raspar cada último byte, sstrip é uma ferramenta boa que está faltando na lista e e pode raspar alguns mais kB.

Por exemplo, quando executado em si strip, pode raspar ~ 2kB .

A partir de um README de idade (ver os comentários no topo da este arquivo de fonte indireta ):

sstrip é uma utilidade pequena que remove os conteúdos no final de um arquivo ELF que não fazem parte da imagem da memória do programa.

executáveis ??maioria ELF são construídas tanto com uma tabela cabeçalho do programa e uma tabela cabeçalho secção. No entanto, apenas o primeiro é necessária a fim para o sistema operacional de carga, link e executar um programa. tentativas para sstrip extrair o cabeçalho ELF, a tabela de cabeçalho do programa, e seu conteúdo, deixando tudo o resto no balde bit. Ela só pode remover partes de o arquivo que ocorrem no final, depois de as peças a serem salvos. Contudo, Isso quase sempre inclui a tabela de cabeçalho de seção, e, ocasionalmente, algumas seções aleatórios que não são usados ??ao executar um programa.

Note que, devido a algumas das informações que ele remove, um sstrip'd executável é rumores de ter problemas com algumas ferramentas. Isso é discutido mais nos comentários da fonte.

Além disso ... para um entretenimento / leitura louca sobre como fazer o menor executável possível, este artigo vale a pena ler.

Para responder a esta necessidade específica:

• Eu quero omitir essas funções (se possível), mas não consigo encontrar o que é chamá-los !! Poderia ser chamado de qualquer número de funções de biblioteca I adivinhar.

Se você quiser analisar sua base de código para ver quem chama o quê, por quem uma dada função está sendo chamado e coisas assim, há uma grande ferramenta para fora lá chamado "Compreender C" fornecido pelo SciTools.

https://scitools.com/

Eu usei-o muitas vezes no passado para realizar a análise de código estático. Ela pode realmente ajudar a determinar árvore de dependência biblioteca. Ele permite navegar facilmente para cima e para baixo da árvore chamada entre outras coisas.

Eles fornecem uma avaliação tempo limitado, então você deve comprar uma licença.

Você poderia olhar para algo como executável compressão .

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