Qual é a diferença entre Arquivo de objeto compartilhado e Arquivo realocável?

0

link diz

The type field tells us what the purpose of the file is. There are a few common file types.

CORE (value 4)
DYN (Shared object file), for libraries (value 3)
EXEC (Executable file), for binaries (value 2)
REL (Relocatable file), before linked into an executable file (value 1)
O

link mostra que um módulo do kernel é REL. Por que é REL não DYN?

Qual é a diferença entre DYN e REL?

Obrigado.

    
por Tim 18.10.2018 / 03:47

2 respostas

1

Consulte o System V ABI , que contém as especificações do formato ELF. Diz

Relocation entries for different object files have slightly different interpretations for the r_offset member.

  • In relocatable files, r_offset holds a section offset. That is, the relocation section itself describes how to modify another section in the file; relocation offsets designate a storage unit within the second section.

  • In executable and shared object files, r_offset holds a virtual address. To make these files’ relocation entries more useful for the dynamic linker, the section offset (file interpretation) gives way to a virtual address (memory interpretation).

Os arquivos realocáveis ainda são totalmente realocáveis, enquanto os objetos compartilhados estão um passo adiante no processo de vinculação e foram amplamente realocados. Os objetos compartilhados só podem ser reposicionados se o código deles for independente da posição (por exemplo, <.> foi criado com a opção -fPIC do GCC).

Os módulos de kernel precisam ser relocáveis sem serem independentes de posição, portanto, eles são enviados como arquivos relocáveis.

    
por 18.10.2018 / 07:13
0

O Linux não usa os métodos ELF para objetos dinâmicos no kernel, o Linux ainda usa um método básico para carregar drivers de meados dos anos 80 e que já funcionavam com o formato a.out . Existem arquivos relocáveis (semelhantes a .o files) que são vinculados ao kernel e carregados.

O método que foi introduzido em meados da década de 1980 funciona dessa maneira, seja chamando um programa que faz o seguinte ou tendo um daemon de espaço do usuário que faz o seguinte:

  • Pegue o arquivo .o do driver ou um arquivo vinculado de vários .o arquivos via ld -o driver -r *.o e execute uma etapa final do link (usando ld ) que vincula esse driver ao endereço de carregamento 0. Isso é necessário, pois as variáveis COMMON não aparecem na saída size .

  • Agora, chame size no arquivo resultante para obter o tamanho necessário para o driver.

  • Abra um driver de carregamento do módulo e use um ioctl para informar a esse driver o tamanho do módulo.

  • O driver de carregamento do módulo chama kmem_alloc() no kernel para segmentos de texto, dados e bss e retorna os endereços retornados por kmem_alloc() na estrutura de resultados de ioctl .

  • Chame o vinculador ( ld ) novamente, mas agora vincule o driver aos endereços que foram retornados pelo driver de carregamento do módulo.

  • Use outra chamada para o driver de carregamento do módulo que instrui esse driver a fazer um "slurp" na variante do driver que foi vinculada aos endereços alocados pelo kernel e coloca o conteúdo do driver no espaço alocado.

  • O driver carregado agora pode ser usado

Se você gosta de olhar para um kernel que usa os métodos ELF, eu recomendo olhar para o kernel do Solaris.

O primeiro arquivo carregado para o Solaris é, por exemplo, /platform/i86pc/kernel/amd64/unix e este arquivo está marcado como excutable que depende de duas "bibliotecas" compartilhadas. Você pode listar isso com a ferramenta ELF padrão dump :

dump -Lv /platform/i86pc/kernel/amd64/unix  

/platform/i86pc/kernel/amd64/unix:

  **** DYNAMIC SECTION INFORMATION ****
.dynamic:
[INDEX] Tag         Value
[1]     NEEDED          genunix
[2]     NEEDED          dtracestubs
[3]     HASH            0xfffffffffb8c1040
[4]     STRTAB          0xfffffffffb8e4e10
[5]     STRSZ           0xf584
[6]     SYMTAB          0xfffffffffb8c9fc0
[7]     SYMENT          0x18
[8]     CHECKSUM        0x4445
[9]     TEXTREL         0
[10]    RELA            0xfffffffffb8f4398
[11]    RELASZ          0x16470
[12]    RELAENT         0x18
[13]    FEATURE_1       PARINIT
[14]    SUNW_CAP        0xfffffffffb8a37a8
[15]    FLAGS           TEXTREL
[16]    FLAGS_1         [ NOHDR ]
[17]    SUNW_STRPAD     0x200
[18]    SUNW_LDMACH     EM_AMD64

file /platform/i86pc/kernel/unix        
/platform/i86pc/kernel/unix:       ELF 32-bit LSB executable 80386 Version 1, dynamically linked, not stripped, no debugging information available

Como você vê aqui, as bibliotecas compartilhadas, das quais o kernel básico depende, são: genunix e dtracestubs .

Então, se você gosta de inicializar um kernel do Solaris, você precisa ter um gerenciador de inicialização que saiba sobre o ELF e seja capaz de carregar e vincular os objetos compartilhados, do qual o kernel depende.

BTW: O Solaris possui um vinculador dinâmico no kernel, portanto, carregar dinamicamente um driver leva menos etapas.

    
por 18.10.2018 / 11:48