vmlinux
Este es el kernel de Linux en un formato de archivo ejecutable vinculado estáticamente. Generalmente, no tiene que preocuparse por este archivo, es solo un paso intermedio en el procedimiento de arranque.
El archivo vmlinux sin procesar puede ser útil para fines de depuración.
vmlinux.bin
Lo mismo que vmlinux, pero en un formato de archivo binario sin formato de arranque. Todos los símbolos y la información de reubicación se descartan. Generado a partir de vmlinux
por objcopy -O binary vmlinux vmlinux.bin
.
vmlinuz
El archivo vmlinux generalmente se comprime con zlib
. Desde 2.6.30 LZMA
y bzip2
también están disponibles. Al agregar más funciones de arranque y descompresión a vmlinuz, la imagen se puede usar para arrancar un sistema con el kernel de vmlinux. La compresión de vmlinux puede ocurrir con zImage o bzImage.
La función decompress_kernel()
maneja la descompresión de vmlinuz en el arranque, un mensaje indica esto:
Decompressing Linux... done
Booting the kernel.
zImagen (make zImage
)
Este es el formato antiguo para núcleos pequeños (comprimido, por debajo de 512 KB). En el arranque, esta imagen se carga con poca memoria (los primeros 640 KB de RAM).
bzImagen (make bzImage
)
El gran zImage (esto no tiene nada que ver con bzip2
), se creó mientras el núcleo crecía y maneja imágenes más grandes (comprimidas, más de 512 KB). La imagen se carga mucho en la memoria (más de 1 MB de RAM). Como los núcleos de hoy en día superan los 512 KB, esta suele ser la forma preferida.
Una inspección en Ubuntu 10.10 muestra:
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
Realice una compilación detallada del kernel y busque los archivos
Este enfoque puede dar una idea, nunca quedará obsoleto y lo ayudará a encontrar fácilmente qué parte del sistema de compilación está haciendo qué.
Una vez que tenga una configuración de compilación que genere uno de los archivos, compile con:
make V=1 |& tee f.log
Modifique un comentario en algún archivo C para forzar un nuevo enlace (por ejemplo, init/main.c
es bueno) si ya ha construido anteriormente.
Ahora, inspeccione f.log
y busca las imágenes de tu interés.
Por ejemplo, en 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
Los archivos delgados se mencionan en:https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Son archivos que solo señalan otros archivos/objetos en lugar de copiarlos.
El kernel pasó de la vinculación incremental a archivos ligeros en v4.9 como se describe en:https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
Interpretación completa del registro
Cuando comenzamos a leer los registros de compilación detallados desde la copia de seguridad, primero vemos:
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
así que esos dos solo están enlazados.
Luego buscamos un poco más para x86/boot/bzImage
y encuentra:
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
es un ejecutable, así que lo ejecutamos, vea el mensaje de ayuda:
Usage: build setup system zoffset.h image
y grep para encontrar la fuente:
arch/x86/boot/tools/build.c
Entonces esta herramienta debe estar generando arch/x86/boot/bzImage
de arch/x86/boot/vmlinux.bin
y otros archivos TODO cuál es el punto de build
exactamente?
Si seguimos arch/x86/boot/vmlinux.bin
vemos que es solo un 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
y arch/x86/boot/compressed/vmlinux
es solo un archivo ELF normal:
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
dice que piggy.o
es, con mucho, el archivo más grande, por lo que lo buscamos y debe provenir 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_
prefijo explicado a continuación.
arch/x86/boot/compressed/piggy.S
contiene:
.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"
consulte también:https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692
arch/x86/boot/compressed/vmlinux.bin.gz
viene 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 viene de:
objcopy -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin
que viene de:
LD vmlinux
que hace:
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
es enorme, pero todos los objetos mostrados son diminutos según ls -l
, así que investigué y aprendí sobre un nuevo ar
característica que no conocía:archivos delgados.
En:
AR built-in.a
la compilación hace:
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 el archivo ligero.
Entonces podemos ver que todos los subarchivos también son delgados, por ejemplo, desde que modifiqué init/main.c
, tenemos:
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 proviene del archivo C a través de un 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
No puedo encontrar el init/.tmp_main.o
a init/main.o
pisar los troncos que es una pena... con:
git grep '\.tmp_'
vemos que probablemente viene de scripts Makefile.build
y está vinculado a CONFIG_MODVERSIONS
que había 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álisis realizado con esta configuración que contiene CONFIG_KERNEL_GZIP=y
.
aarch64 arch/arm64/boot/Image
Solo un objcopy
sin comprimir de vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
se obtiene básicamente de la misma manera que para x86 a través de archivos delgados.
arch/arm/boot/zImage
Muy similar a X86 con un vmlinux
comprimido , pero sin magia build.c
paso. Resumen de la cadena de llamadas:
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
QEMU v4.0.0 puede arrancar desde bzImage pero no desde vmlinux
Esta es otra diferencia práctica importante:https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu