Estou tentando desmontar um arquivo composto que consiste em várias partes, uma das quais é um kernel descompactado imprensado entre vários outros arquivos. Estou tentando encontrar o comprimento exato da parte do kernel, o que está sendo difícil.
Há alguma indicação no cabeçalho vmlinux de quantos dados o bootloader deve ler antes de executar, ou é assumido que todo o conteúdo do arquivo vmlinux deve ser carregado na transferência do bootloader?
Responder1
A resposta rápida é "não", mas se esta for uma imagem ELF, então com alguns hackers você provavelmente poderá encontrar o kernel. Veja o readelf
hack abaixo.
O bootloader é responsável por saber o formato de qualquer arquivo no qual residem o kernel e o sistema de arquivos raiz. Isso inclui saber o tamanho do arquivo do kernel, em qualquer formato. No PowePC e Blackfin, o bootloader é responsável por descompactar todo o kernel, se estiver compactado, e gravá-lo em seu local final na RAM. No ARM, o kernel pode ser autodescompactado e o bootloader só precisa copiar o arquivo bruto do kernel para um local conveniente na RAM e iniciar a execução.
Se o kernel for autodescompactado, os símbolos que indicam o tamanho do arquivo do kernel compactado podem ou não estar em algum lugar do código de descompactação no início do arquivo, dependendo do algoritmo de descompactação usado, mas você não tem como saber onde está sem um mapa de vinculador para a construção específica do kernel. Certamente o bootloader não tem como saber.
O próprio código do kernel descompactado é delimitado por 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 qualquer initramfs incluído, se um initramfs tiver sido vinculado ao binário do kernel. A extensão do initramfs é definida pelo vinculador em dois símbolos do kernel __initramfs_start
e __initramfs_end
. Os bootloaders geralmente não têm a capacidade de ler a tabela de símbolos do kernel (está no System.map
arquivo) e, sem essa capacidade, eles 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. É determinado no momento do link e pode variar dependendo da configuração de compilação do kernel.
Para um kernel descompactado no formato ELF você provavelmente pode 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 então fazer readelf -e
ou objdump -h
no restante do arquivo a partir deste ponto para encontrar a seção com o maior deslocamento do arquivo ( .shstrtab
). Adicione o tamanho da seção a esse deslocamento e isso levará você ao final do vmlinux. Testei esse método usando um PPC vmlinux não removido e obtive um tamanho que correspondia exatamente ao tamanho do arquivo vnlinux independente. Depois de remover o kernel, esse método deu um resultado de 1283 bytes a menos do tamanho da imagem removida.
Os sistemas embarcados geralmente usam um formato de arquivo para mkimage
compactar o kernel, rootfs, árvore de dispositivos e outros componentes. O U-boot, por exemplo, reconhece mkimage, portanto sabe onde o binário do kernel começa e termina dentro do arquivo mkimage e sabe se o kernel está compactado ou não e em qual endereço de RAM gravar o arquivo do kernel.