O cabeçalho do vmlinux contém o tamanho da imagem do kernel?

4

Estou tentando desmontar um arquivo composto que consiste em várias partes, uma das quais é um kernel descompactado entre vários outros arquivos. Eu estou tentando encontrar o comprimento exato da parte do kernel que está se mostrando difícil.

Existe alguma indicação no cabeçalho do vmlinux da quantidade de dados que o gerenciador de inicialização deve ler antes de executar, ou presume-se que todo o conteúdo do arquivo vmlinux deve ser carregado no handoff do carregador de inicialização?

    
por Peter Grace 01.05.2013 / 15:50

1 resposta

2

A resposta rápida é "não", mas se esta é uma imagem ELF, então com algum hacking você pode encontrar o kernel. Veja o readelf hack abaixo.

O gerenciador de inicialização é responsável por conhecer o formato de qualquer arquivo no qual o kernel e o sistema de arquivos raiz residem. Isso inclui conhecer o tamanho do arquivo do kernel, em qualquer que seja o formato. No PowePC e no Blackfin, o gerenciador de inicialização é responsável por descompactar todo o kernel se ele for compactado e gravá-lo no local final na RAM. No ARM, o kernel pode ser auto-descompactado e o bootloader só precisa copiar o arquivo do kernel bruto para um local conveniente na RAM e iniciar a execução.

Se o kernel é auto-descompactado, os símbolos que indicam o tamanho do arquivo do kernel compactado podem ou não estar em algum lugar no código de descompressão no início do arquivo, dependendo do algoritmo de descompactação usado, mas você tem nenhuma maneira de saber onde sem um mapa de link para a compilação específica do kernel. Certamente o bootloader não tem como saber.

O próprio código do kernel descompactado é colocado entre dois símbolos, _stext e _end cujos endereços são o início e o fim do próprio kernel, mas não incluem a extensão de nenhum initramfs incluído, se um initramfs tiver sido vinculado no binário do kernel. A extensão do initramfs é definida pelo vinculador em dois símbolos do kernel, __initramfs_start e __initramfs_end . Inicialmente, os carregadores de inicialização não têm a capacidade de ler a tabela de símbolos do kernel (está no arquivo System.map ) e sem esse recurso não teriam como saber onde os símbolos _end e __initrams_end estão no arquivo do kernel. Ou seja, a posição dos símbolos não é um deslocamento fixo desde o início do arquivo binário. Ele é determinado no momento do link e pode variar dependendo da configuração de compilação do kernel.

Para um kernel descompactado no formato ELF, é possível identificar o início do arquivo vmlinux procurando pelo cabeçalho ELF ( 177 E L F no od -c dump do arquivo composto). Você pode fazer readelf -e ou objdump -h no restante do arquivo a partir desse ponto para encontrar a seção com o maior deslocamento de arquivo ( .shstrtab ). Adicione o tamanho da seção a esse deslocamento e isso leva você ao final do vmlinux. Eu testei esse método usando um vmlinux PPC não-limitado e obtive um tamanho que correspondesse exatamente ao tamanho do arquivo vnlinux independente. Depois de extrair o kernel, este método deu um resultado que ficou 1283 bytes aquém do tamanho da imagem removida.

Sistemas embarcados geralmente usam um arquivo como mkimage para empacotar o kernel, rootfs, árvore de dispositivos e outros componentes. U-boot por exemplo é mkimage aware, então ele sabe onde o binário do kernel começa e termina dentro do arquivo mkimage e ele sabe se o kernel está compactado ou não e em qual endereço de RAM gravar o arquivo do kernel.

    
por 02.05.2013 / 19:06