vmlinux
Dies ist der Linux-Kernel in einem statisch verknüpften ausführbaren Dateiformat. Im Allgemeinen müssen Sie sich um diese Datei keine Gedanken machen, sie ist nur ein Zwischenschritt im Bootvorgang.
Die rohe vmlinux-Datei kann für Debugging-Zwecke nützlich sein.
vmlinux.bin
Dasselbe wie vmlinux, aber in einem bootfähigen rohen Binärdateiformat. Alle Symbole und Verschiebungsinformationen werden verworfen. Generiert aus vmlinux
bis objcopy -O binary vmlinux vmlinux.bin
.
vmlinuz
Die vmlinux-Datei wird normalerweise mit zlib
komprimiert . Seit 2.6.30 LZMA
und bzip2
sind ebenfalls erhältlich. Durch Hinzufügen weiterer Boot- und Dekomprimierungsfunktionen zu vmlinuz kann das Image zum Booten eines Systems mit dem vmlinux-Kernel verwendet werden. Die Komprimierung von vmlinux kann mit zImage oder bzImage erfolgen.
Die Funktion decompress_kernel()
behandelt die Dekomprimierung von vmlinuz beim Booten, eine Meldung weist darauf hin:
Decompressing Linux... done
Booting the kernel.
zBild (make zImage
)
Dies ist das alte Format für kleine Kernel (komprimiert, unter 512 KB). Beim Booten wird dieses Image in den Speicher niedrig geladen (die ersten 640 KB des RAM).
bzImage (make bzImage
)
Das große zImage (hat nichts mit bzip2
zu tun ), wurde erstellt, während der Kernel wuchs und größere Bilder verarbeitet (komprimiert, über 512 KB). Das Bild wird hoch in den Speicher geladen (über 1 MB RAM). Da die heutigen Kernel weit über 512 KB groß sind, ist dies normalerweise der bevorzugte Weg.
Eine Überprüfung auf Ubuntu 10.10 zeigt:
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
Führen Sie einen ausführlichen Kernel-Build durch und suchen Sie nach den Dateien
Dieser Ansatz kann einen Einblick geben, wird nie veraltet sein und wird Ihnen helfen, leicht herauszufinden, welcher Teil des Build-Systems was tut.
Sobald Sie eine Build-Konfiguration haben, die eine der Dateien generiert, erstellen Sie mit:
make V=1 |& tee f.log
Ändern Sie einen Kommentar zu einer C-Datei, um eine erneute Verknüpfung zu erzwingen (z. B. init/main.c
ist gut), wenn Sie bereits zuvor gebaut haben.
Untersuchen Sie jetzt f.log
und suchen Sie nach den gewünschten Bildern.
Zum Beispiel werden wir in v4.19 zu folgendem Schluss kommen:
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
Dünne Archive werden erwähnt unter:https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Sie sind Archive, die nur auf andere Archive/Objekte verweisen, anstatt sie zu kopieren.
Der Kernel wechselte in v4.9 von inkrementellem Linken zu dünnen Archiven, wie beschrieben unter:https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
Vollständige Protokollinterpretation
Wenn wir beginnen, die ausführlichen Build-Protokolle von der Sicherung zu lesen, sehen wir zuerst:
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
diese beiden sind also nur symbolisch verknüpft.
Dann suchen wir etwas weiter nach x86/boot/bzImage
und finde:
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
ist eine ausführbare Datei, also führen wir sie aus, siehe Hilfenachricht:
Usage: build setup system zoffset.h image
und grep, um die Quelle zu finden:
arch/x86/boot/tools/build.c
Dieses Tool muss also arch/x86/boot/bzImage
generieren ab arch/x86/boot/vmlinux.bin
und andere Dateien TODO was ist der Sinn von build
genau?
Wenn wir arch/x86/boot/vmlinux.bin
befolgen wir sehen, dass es nur ein objcopy
ist ab arch/x86/boot/compressed/vmlinux
:
objcopy \
-O binary \
-R .note \
-R .comment \
-S arch/x86/boot/compressed/vmlinux \
arch/x86/boot/vmlinux.bin
und arch/x86/boot/compressed/vmlinux
ist nur eine normale ELF-Datei:
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
sagt, dass piggy.o
ist bei weitem die größte Datei, also suchen wir danach, und sie muss stammen von:
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äfix unten erklärt.
arch/x86/boot/compressed/piggy.S
enthält:
.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"
siehe auch:https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692
arch/x86/boot/compressed/vmlinux.bin.gz
kommt von:
cat arch/x86/boot/compressed/vmlinux.bin arch/x86/boot/compressed/vmlinux.relocs | \
gzip -n -f -9 > arch/x86/boot/compressed/vmlinux.bin.gz
was kommt von:
objcopy -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin
was kommt von:
LD vmlinux
was bedeutet:
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
ist riesig, aber alle gezeigten Objekte sind winzig gemäß ls -l
, also habe ich recherchiert und etwas über einen neuen ar
erfahren Funktion, von der ich nichts wusste:dünne Archive.
Unter:
AR built-in.a
der Build tut:
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
gibt das dünne Archiv an.
Wir können dann sehen, dass alle Unterarchive auch dünn sind, z. B. seit ich init/main.c
geändert habe , haben wir:
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
die schließlich aus der C-Datei durch einen Befehl wie folgt kommt:
gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c
Ich kann init/.tmp_main.o
nicht finden bis init/main.o
Treten Sie auf die Protokolle, was eine Schande ist ... mit:
git grep '\.tmp_'
wir sehen, dass das wahrscheinlich von scripts Makefile.build
kommt und ist mit CONFIG_MODVERSIONS
verknüpft die ich aktiviert hatte:
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
Die Analyse wurde mit dieser Konfiguration durchgeführt, die CONFIG_KERNEL_GZIP=y
enthält .
aarch64 arch/arm64/boot/Image
Nur ein unkomprimiertes objcopy
ab vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
wird im Grunde genauso wie für x86 durch die dünnen Archive erhalten.
arch/arm/boot/zImage
Sehr ähnlich zu X86 mit einem gezippten vmlinux
, aber kein magisches build.c
Schritt. Zusammenfassung der Anrufkette:
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 kann von bzImage booten, aber nicht von vmlinux
Dies ist ein weiterer wichtiger praktischer Unterschied:https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu