Pergunta

Se bem entendi, a seção .bss em arquivos ELF é usado para alocar espaço para variáveis ??de zero-inicializado. Nossa cadeia de ferramenta produz arquivos ELF, daí a minha pergunta: será que a secção .bss realmente tem que conter todos os zeros? Parece um terrível desperdício de espaços de forma que quando, por exemplo, eu alocar uma matriz megabyte dez global, que resulta em megabytes dez de zeros no arquivo ELF. Que eu estou vendo errado aqui?

Foi útil?

Solução

Tem sido algum tempo desde que eu trabalhei com ELF. Mas eu acho que eu ainda me lembro dessas coisas. Não, ele não contém fisicamente aqueles zeros. Se você olhar em um cabeçalho do programa arquivo ELF, então você vai ver cada cabeçalho tem dois números: Um é o tamanho do arquivo. E outro é o tamanho que a secção tem quando alocados na memória virtual (readelf -l ./a.out):

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x00454 0x00454 R E 0x1000
  LOAD           0x000454 0x08049454 0x08049454 0x00104 0x61bac RW  0x1000
  DYNAMIC        0x000468 0x08049468 0x08049468 0x000d0 0x000d0 RW  0x4
  NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

Os cabeçalhos do tipo LOAD é a única que são copiados para a memória virtual quando o arquivo é carregado para execução. Outros cabeçalhos conter outras informações, como as bibliotecas compartilhadas que são necessárias. Como você vê, o FileSize e MemSiz diferem significativamente para o cabeçalho que contém a seção bss (o segundo LOAD um):

0x00104 (file-size) 0x61bac (mem-size)

Para que este código exemplo:

int a[100000];
int main() { }

A especificação ELF diz que a parte de um segmento que a mem-tamanho é maior do que o tamanho do arquivo é apenas preenchido com zeros na memória virtual. O segmento de mapeamento secção do segundo cabeçalho LOAD é assim:

03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss

Portanto, há algumas outras seções lá também. Para C ++ construtor / destruidores. A mesma coisa para Java. Em seguida, ele contém uma cópia da seção .dynamic e outras coisas úteis para a ligação dinâmica (eu acredito este é o local que contém as bibliotecas compartilhadas necessárias entre outras coisas). Depois que a seção .data que contém globals inicializado e variáveis ??estáticas locais. No final, aparece seção .bss, que é preenchido por zeros no tempo de carregamento porque o arquivo de tamanho não cobri-lo.

A propósito, você pode ver no qual a saída de seção um símbolo específico vai ser colocado usando a opção -M vinculador. Para gcc, você usa -Wl,-M para colocar a opção até o vinculador. O exemplo mostra que acima a é atribuída dentro .bss. Pode ajudá-lo a verificar se os objetos não inicializados realmente acabar em .bss e não em outro lugar:

.bss            0x08049560    0x61aa0
 [many input .o files...]
 *(COMMON) 
 *fill*         0x08049568       0x18 00
 COMMON         0x08049580    0x61a80 /tmp/cc2GT6nS.o
                0x08049580                a
                0x080ab000                . = ALIGN ((. != 0x0)?0x4:0x1) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                _end = .

GCC mantém globals não inicializadas em uma seção COMMON por padrão, para compatibilidade com compiladores antigos, que permitem ter globals definidas duas vezes em um programa sem vários erros de definição. Use -fno-common fazer GCC usar as seções .bss para arquivos objeto (não fazer a diferença para a final vinculado executável, porque como você pode ver que vai entrar em uma seção de saída .bss de qualquer maneira. Isso é controlado pelo vinculador roteiro . Indique-a com ld -verbose). Mas isso não deve assustar você, é apenas um detalhe interno. Veja a página de manual do gcc.

Outras dicas

A seção .bss em um arquivo ELF é usado para dados estáticos que é não inicializado por meio de programação, mas garantido para ser ajustado para zero em tempo de execução. Aqui está um pequeno exemplo que irá explicar a diferença.

int main() {
    static int bss_test1[100];
    static int bss_test2[100] = {0};
    return 0;
}

Neste caso bss_test1 é colocado no .bss uma vez que é inicializado. bss_test2 no entanto é colocado no segmento .data juntamente com um grupo de zeros. O carregador de tempo de execução basicamente aloca a quantidade de espaço reservado para o .bss e zeros-lo antes de qualquer código userland começa a executar.

Você pode ver a diferença usando objdump, nm, ou utilitários semelhantes:

moozletoots$ objdump -t a.out | grep bss_test
08049780 l     O .bss   00000190              bss_test1.3
080494c0 l     O .data  00000190              bss_test2.4

Este é geralmente um dos primeiros surpreende que desenvolvedores de sistemas embarcados correr em ... nunca estática Inicializar a zero explicitamente. O carregador de tempo de execução (geralmente) cuida disso. Assim que você inicializar nada explicitamente, você está dizendo ao compilador / vinculador para incluir os dados na imagem executável.

seção .bss A não é armazenado em um arquivo executável. Das seções mais comuns (.text, .data, .bss), única .text (código real) e .data (dados inicializado) estão presentes em um arquivo ELF.

Isso é correto, .bss não está presente fisicamente no arquivo, e não apenas as informações sobre seu tamanho está presente para o carregador dinâmico para alocar a seção .bss para o programa aplicativo. Como regra de ouro única CARGA, TLS Segmento fica a memória para o programa de aplicação, o descanso são usados ??para carregador dinâmico.

Sobre o arquivo executável estática, seções BSS também é dado espaço no execuatble

Incorporado aplicação onde não há carregador isso é comum.

Suman

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