vmlinux
Il s'agit du noyau Linux dans un format de fichier exécutable lié statiquement. Généralement, vous n'avez pas à vous soucier de ce fichier, c'est juste une étape intermédiaire dans la procédure de démarrage.
Le fichier vmlinux brut peut être utile à des fins de débogage.
vmlinux.bin
Identique à vmlinux, mais dans un format de fichier binaire brut amorçable. Tous les symboles et informations de relocalisation sont ignorés. Généré à partir de vmlinux
par objcopy -O binary vmlinux vmlinux.bin
.
vmlinuz
Le fichier vmlinux est généralement compressé avec zlib
. Depuis le 2.6.30 LZMA
et bzip2
sont également disponibles. En ajoutant des capacités de démarrage et de décompression supplémentaires à vmlinuz, l'image peut être utilisée pour démarrer un système avec le noyau vmlinux. La compression de vmlinux peut se produire avec zImage ou bzImage.
La fonction decompress_kernel()
gère la décompression de vmlinuz au démarrage, un message l'indique :
Decompressing Linux... done
Booting the kernel.
zImage (make zImage
)
C'est l'ancien format pour les petits noyaux (compressé, inférieur à 512 Ko). Au démarrage, cette image est chargée en mémoire (les premiers 640 Ko de RAM).
bzImage (make bzImage
)
Le grand zImage (cela n'a rien à voir avec bzip2
), a été créé pendant la croissance du noyau et gère des images plus grandes (compressées, plus de 512 Ko). L'image est chargée en mémoire (au-dessus de 1 Mo de RAM). Comme les noyaux d'aujourd'hui font bien plus de 512 Ko, c'est généralement la méthode préférée.
Une inspection sur Ubuntu 10.10 montre :
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
Faites une compilation détaillée du noyau et recherchez les fichiers
Cette approche peut donner un aperçu, ne sera jamais obsolète et vous aidera à trouver facilement quelle partie du système de construction fait quoi.
Une fois que vous avez une configuration de construction qui génère l'un des fichiers, construisez avec :
make V=1 |& tee f.log
Modifier un commentaire sur un fichier C pour forcer une reconnexion (par exemple init/main.c
est un bon) si vous avez déjà construit précédemment.
Maintenant, inspectez f.log
et recherchez les images qui vous intéressent.
Par exemple, sur la v4.19, nous conclurons 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
Les archives minces sont mentionnées sur :https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Ce sont des archives qui pointent simplement vers d'autres archives/objets au lieu de les copier.
Le noyau est passé de la liaison incrémentielle aux archives légères dans la v4.9, comme décrit sur :https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
Interprétation complète du journal
Lorsque nous commençons à lire les journaux de construction détaillés à partir de la sauvegarde, nous voyons d'abord :
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
donc ces deux sont simplement liés symboliquement.
Ensuite, nous cherchons un peu plus loin pour x86/boot/bzImage
et trouvez :
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
est un exécutable, nous l'exécutons donc, voir le message d'aide :
Usage: build setup system zoffset.h image
et grep pour trouver la source :
arch/x86/boot/tools/build.c
Cet outil doit donc générer arch/x86/boot/bzImage
à partir de arch/x86/boot/vmlinux.bin
et autres fichiers TODO à quoi sert build
exactement ?
Si nous suivons arch/x86/boot/vmlinux.bin
on voit que c'est juste un objcopy
à partir de arch/x86/boot/compressed/vmlinux
:
objcopy \
-O binary \
-R .note \
-R .comment \
-S arch/x86/boot/compressed/vmlinux \
arch/x86/boot/vmlinux.bin
et arch/x86/boot/compressed/vmlinux
est juste un fichier 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
dit que piggy.o
est de loin le fichier le plus volumineux, nous le recherchons donc, et il doit 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_
préfixe expliqué ci-dessous.
arch/x86/boot/compressed/piggy.S
contient :
.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"
voir aussi :https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692
arch/x86/boot/compressed/vmlinux.bin.gz
vient 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
qui vient de :
objcopy -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin
qui vient de :
LD vmlinux
qui fait :
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
est énorme, mais tous les objets affichés sont minuscules selon ls -l
, j'ai donc fait des recherches et découvert un nouveau ar
fonctionnalité que je ne connaissais pas :les archives légères.
À :
AR built-in.a
la construction fait :
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
spécifie l'archive légère.
Nous pouvons alors voir que toutes les sous-archives sont également minces, par exemple depuis que j'ai modifié init/main.c
, nous avons :
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
qui vient finalement du fichier C via une commande comme :
gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c
Je ne trouve pas le init/.tmp_main.o
à init/main.o
marcher sur les bûches c'est dommage... avec :
git grep '\.tmp_'
nous voyons que cela vient probablement de scripts Makefile.build
et est lié à CONFIG_MODVERSIONS
que j'avais activé :
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
Analyse faite avec cette config qui contient CONFIG_KERNEL_GZIP=y
.
aarch64 arch/arm64/boot/Image
Juste un objcopy
non compressé à partir de vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
est obtenu essentiellement de la même manière que pour x86 via les archives légères.
arch/arm/boot/zImage
Très similaire à X86 avec un vmlinux
compressé , mais pas de magie build.c
marcher. Résumé de la chaîne d'appel :
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 peut démarrer à partir de bzImage mais pas de vmlinux
C'est une autre différence pratique importante :https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu