Ao navegar pelos Makefiles do Kernel, encontrei estes termos. Então, eu gostaria de saber qual é a diferença entre vmlinux
, vmlinuz
, vmlinux.bin
, zimage
e bzimage
?
vmlinux
Este é o kernel do Linux em um formato de arquivo executável vinculado estaticamente. Geralmente, você não precisa se preocupar com este arquivo, é apenas uma etapa intermediária no procedimento de inicialização.
O arquivo vmlinux bruto pode ser útil para fins de depuração.
vmlinux.bin
O mesmo que o vmlinux, mas em um formato de arquivo binário bruto inicializável. Todos os símbolos e informações de realocação são descartados. Gerado a partir de vmlinux
por objcopy -O binary vmlinux vmlinux.bin
.
vmlinuz
O arquivo vmlinux geralmente é compactado com zlib
. Desde 2.6.30 LZMA
e bzip2
Também estão disponíveis. Adicionando mais recursos de inicialização e descompactação ao vmlinuz, a imagem pode ser usada para inicializar um sistema com o kernel do vmlinux. A compactação do vmlinux pode ocorrer com zImage ou bzImage.
A função decompress_kernel()
lida com a descompressão do vmlinuz na inicialização, uma mensagem indica o seguinte:
Decompressing Linux... done
Booting the kernel.
zImage (make zImage
)
Este é o formato antigo para kernels pequenos (compactados, abaixo de 512 KB). Na inicialização, essa imagem é carregada com pouca memória (os primeiros 640 KB da RAM).
bzImage (make bzImage
)
O grande zImage (isso não tem nada a ver com bzip2
), Foi criado enquanto o kernel cresceu e manipula imagens maiores (compactadas, acima de 512 KB). A imagem é carregada com muita memória (acima de 1 MB de RAM). Como os kernels de hoje têm mais de 512 KB, essa é geralmente a maneira preferida.
Uma inspeção no Ubuntu 10.10 mostra:
ls -lh /boot/vmlinuz-$(uname -r)
-rw-r--r-- 1 root root 4.1M 2010-11-24 12:21 /boot/vmlinuz-2.6.35-23-generic
file /boot/vmlinuz-$(uname -r)
/boot/vmlinuz-2.6.35-23-generic: Linux kernel x86 boot executable bzImage, version 2.6.35-23-generic ([email protected], RO-rootFS, root_dev 0x6801, swap_dev 0x4, Normal VGA
Faça uma compilação detalhada do kernel e procure os arquivos
Essa abordagem pode fornecer algumas informações, nunca ficará desatualizada e ajudará você a encontrar facilmente qual parte do sistema de compilação está fazendo o que.
Depois de ter uma configuração de construção que gera um dos arquivos, construa com:
make V=1 |& tee f.log
Modifique um comentário em algum arquivo C para forçar um novo link (por exemplo, init/main.c
é bom) se você já construiu anteriormente.
Agora, inspecione f.log
e pesquise as imagens de seu interesse.
Por exemplo, na v4.19, concluiremos que:
init/main.c
|
| gcc -c
|
v
init/.tmp_main.o
|
| CONFIG_MODVERSIONS stuff
|
v
init/main.o
|
| ar T (thin archive)
|
v
init/built-in.a
|
| ar T (thin archive)
|
v
built-in.a
|
| ld
|
v
vmlinux (regular ELF file)
|
| objcopy
|
v
Arch/x86/boot/compressed/vmlinux.bin
|
| GZIP
|
v
Arch/x86/boot/compressed/vmlinux.bin.gz
|
| .incbin
|
v
Arch/x86/boot/compressed/piggy.S
|
| gcc -c
|
v
Arch/x86/boot/compressed/piggy.o
|
| ld
|
v
Arch/x86/boot/compressed/vmlinux (regular ELF file with gzipped code)
|
| objcopy
|
v
Arch/x86/boot/vmlinux.bin
|
| Arch/x86/boot/tools/build.c
|
v
Arch/x86/boot/bzImage
Os arquivos compactados são mencionados em: https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Eles são arquivos que apenas apontam outros arquivos/objetos em vez de copiá-los.
O kernel passou da vinculação incremental para os arquivos compactados na v4.9, conforme descrito em: https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
Interpretação completa do log
Quando começamos a ler os logs de construção detalhados a partir do backup, primeiro vemos:
ln -fsn ../../x86/boot/bzImage ./Arch/x86_64/boot/bzImage
então esses dois são apenas simbolizados.
Em seguida, pesquisamos um pouco mais por x86/boot/bzImage
e encontra:
Arch/x86/boot/tools/build \
Arch/x86/boot/setup.bin \
Arch/x86/boot/vmlinux.bin \
Arch/x86/boot/zoffset.h \
Arch/x86/boot/bzImage
Arch/x86/boot/tools/build
é um executável, portanto, nós o executamos, veja a mensagem de ajuda:
Usage: build setup system zoffset.h image
e grep para encontrar a fonte:
Arch/x86/boot/tools/build.c
Portanto, essa ferramenta deve estar gerando Arch/x86/boot/bzImage
de Arch/x86/boot/vmlinux.bin
e outros arquivos TODO, qual é o sentido de build
exatamente?
Se seguirmos Arch/x86/boot/vmlinux.bin
vemos que é apenas um objcopy
de Arch/x86/boot/compressed/vmlinux
:
objcopy \
-O binary \
-R .note \
-R .comment \
-S Arch/x86/boot/compressed/vmlinux \
Arch/x86/boot/vmlinux.bin
e Arch/x86/boot/compressed/vmlinux
é apenas um arquivo ELF comum:
ld \
-m elf_x86_64 \
-z noreloc-overflow \
-pie \
--no-dynamic-linker \
-T Arch/x86/boot/compressed/vmlinux.lds \
Arch/x86/boot/compressed/head_64.o \
Arch/x86/boot/compressed/misc.o \
Arch/x86/boot/compressed/string.o \
Arch/x86/boot/compressed/cmdline.o \
Arch/x86/boot/compressed/error.o \
Arch/x86/boot/compressed/piggy.o \
Arch/x86/boot/compressed/cpuflags.o \
Arch/x86/boot/compressed/early_serial_console.o \
Arch/x86/boot/compressed/kaslr.o \
Arch/x86/boot/compressed/kaslr_64.o \
Arch/x86/boot/compressed/mem_encrypt.o \
Arch/x86/boot/compressed/pgtable_64.o \
-o Arch/x86/boot/compressed/vmlinux
ls -hlSr
diz que piggy.o
é de longe o maior arquivo, então procuramos por ele e deve vir de:
gcc \
-Wp,-MD,Arch/x86/boot/compressed/.piggy.o.d \
-nostdinc \
-Ilinux/Arch/x86/include \
-I./Arch/x86/include/generated \
-Ilinux/include \
-I./include \
-Ilinux/Arch/x86/include/uapi \
-I./Arch/x86/include/generated/uapi \
-Ilinux/include/uapi \
-I./include/generated/uapi \
-include linux/include/linux/kconfig.h \
-D__KERNEL__ \
-m64 \
-O2 \
-fno-strict-aliasing \
-fPIE \
-DDISABLE_BRANCH_PROFILING \
-mcmodel=small \
-mno-mmx \
-mno-sse \
-ffreestanding \
-fno-stack-protector \
-Wno-pointer-sign \
-D__Assembly__ \
-c \
-o Arch/x86/boot/compressed/.tmp_piggy.o \
Arch/x86/boot/compressed/piggy.S
.tmp_
prefixo explicado abaixo.
Arch/x86/boot/compressed/piggy.S
contém:
.incbin "Arch/x86/boot/compressed/vmlinux.bin.gz"
consulte também: https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692
Arch/x86/boot/compressed/vmlinux.bin.gz
vem de:
cat Arch/x86/boot/compressed/vmlinux.bin Arch/x86/boot/compressed/vmlinux.relocs | \
gzip -n -f -9 > Arch/x86/boot/compressed/vmlinux.bin.gz
que vem de:
objcopy -R .comment -S vmlinux Arch/x86/boot/compressed/vmlinux.bin
que vem de:
LD vmlinux
qual faz:
ld \
-m elf_x86_64 \
-z max-page-size=0x200000 \
--emit-relocs \
--build-id \
-o vmlinux \
-T ./Arch/x86/kernel/vmlinux.lds \
--whole-archive \
built-in.a \
--no-whole-archive \
--start-group \
lib/lib.a \
Arch/x86/lib/lib.a \
--end-group \
.tmp_kallsyms2.o
vmlinux
é enorme, mas todos os objetos mostrados são pequenos, de acordo com ls -l
, então pesquisei e aprendi sobre um novo recurso ar
que eu não conhecia: arquivos finos.
Em:
AR built-in.a
a construção faz:
ar \
rcsTPD \
built-in.a \
Arch/x86/kernel/head_64.o \
Arch/x86/kernel/head64.o \
Arch/x86/kernel/ebda.o \
Arch/x86/kernel/platform-quirks.o \
init/built-in.a \
usr/built-in.a \
Arch/x86/built-in.a \
kernel/built-in.a \
certs/built-in.a \
mm/built-in.a \
fs/built-in.a \
ipc/built-in.a \
security/built-in.a \
crypto/built-in.a \
block/built-in.a \
lib/built-in.a \
Arch/x86/lib/built-in.a \
drivers/built-in.a \
sound/built-in.a \
firmware/built-in.a \
Arch/x86/pci/built-in.a \
Arch/x86/power/built-in.a \
Arch/x86/video/built-in.a \
net/built-in.a \
virt/built-in.a
T
especifica o arquivo morto.
Podemos ver que todos os subarquivos também são finos, por exemplo, desde que modifiquei init/main.c
, temos:
ar \
rcSTPD \
init/built-in.a \
init/main.o \
init/version.o \
init/do_mounts.o \
init/do_mounts_initrd.o \
init/initramfs.o \
init/calibrate.o \
init/init_task.o
que finalmente vem do arquivo C através de um comando como:
gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c
Não consigo encontrar o init/.tmp_main.o
para init/main.o
pise nos logs, o que é uma pena ... com:
git grep '\.tmp_'
vemos que provavelmente vem de scripts Makefile.build
e está vinculado a CONFIG_MODVERSIONS
que eu havia habilitado:
ifndef CONFIG_MODVERSIONS
cmd_cc_o_c = $(CC) $(c_flags) -c -o [email protected] $<
else
# When module versioning is enabled the following steps are executed:
# o compile a .tmp_<file>.o from <file>.c
# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
# not export symbols, we just rename .tmp_<file>.o to <file>.o and
# are done.
# o otherwise, we calculate symbol versions using the good old
# genksyms on the preprocessed source and postprocess them in a way
# that they are usable as a linker script
# o generate <file>.o from .tmp_<file>.o using the linker to
# replace the unresolved symbols __crc_exported_symbol with
# the actual value of the checksum generated by genksyms
cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
cmd_modversions_c = \
if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
$(LD) $(KBUILD_LDFLAGS) -r -o [email protected] $(@D)/.tmp_$(@F) \
-T $(@D)/.tmp_$(@F:.o=.ver); \
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
else \
mv -f $(@D)/.tmp_$(@F) [email protected]; \
fi;
endif
Análise feita com esta configuração que contém CONFIG_KERNEL_GZIP=y
.
aarch64 Arch/arm64/boot/Image
Apenas um objcopy
descompactado de vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux Arch/arm64/boot/Image
vmlinux
é obtido basicamente da mesma maneira que no x86 nos arquivos compactados.
Arch/arm/boot/zImage
Muito semelhante ao X86 com um vmlinux
zipado, mas sem mágica build.c
degrau. Resumo da cadeia de chamadas:
objcopy -O binary -R .comment -S Arch/arm/boot/compressed/vmlinux Arch/arm/boot/zImage
ld \
-EL \
--defsym _kernel_bss_size=469592 \
-p \
--no-undefined \
-X \
-T Arch/arm/boot/compressed/vmlinux.lds \
Arch/arm/boot/compressed/head.o \
Arch/arm/boot/compressed/piggy.o \
Arch/arm/boot/compressed/misc.o \
Arch/arm/boot/compressed/decompress.o \
Arch/arm/boot/compressed/string.o \
Arch/arm/boot/compressed/hyp-stub.o \
Arch/arm/boot/compressed/lib1funcs.o \
Arch/arm/boot/compressed/ashldi3.o \
Arch/arm/boot/compressed/bswapsdi2.o \
-o Arch/arm/boot/compressed/vmlinux
gcc \
-c \
-o Arch/arm/boot/compressed/piggy.o \
linux/Arch/arm/boot/compressed/piggy.S
.incbin "Arch/arm/boot/compressed/piggy_data"
cat Arch/arm/boot/compressed/../Image | gzip -n -f -9 > Arch/arm/boot/compressed/piggy_data
objcopy -O binary -R .comment -S vmlinux Arch/arm/boot/Image
O QEMU v4.0.0 pode inicializar a partir do bzImage, mas não o vmlinux
Essa é outra diferença prática importante: https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qem
Está tudo aqui: http://en.wikipedia.org/wiki/Vmlinux
vmlinux :
Um formato de arquivo do kernel Linux não compactado e não inicializável, apenas uma etapa intermediária para produzir vmlinuz
.
vmlinuz :
Um arquivo de kernel Linux compactado e inicializável. Na verdade, é um arquivo zImage
ou bzImage
.
zImage :
Para kernels antigos, basta encaixar 640k
tamanho da ram.
bzImage :Big zImage
, não 640k
limite de tamanho de ram, pode ser muito maior.
Por favor, consulte este documento: vmlinuz Definition .
bzImage é o destino usado para arquiteturas x86 que trabalham com o BIOS do PC. Por outro lado, zImage é um destino específico da arquitetura mais comumente usado para dispositivos incorporados e funciona bem com seus gerenciadores de inicialização.