Erstellen Sie einen ausführlichen Kernel und suchen Sie nach den Dateien
Dieser Ansatz kann einige Einblicke geben, wird nie veraltet sein und Ihnen helfen, auf einfache Weise 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 Neuverknüpfung zu erzwingen (z. B. init/main.c
eine gute), wenn Sie diese bereits zuvor erstellt haben.
Überprüfen Sie nun die gewünschten f.log
Bilder und suchen Sie sie.
In Version 4.19 werden wir beispielsweise Folgendes feststellen:
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
Thin-Archive werden erwähnt unter: https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Es handelt sich um Archive, die nur auf andere Archive / Objekte verweisen, anstatt sie zu kopieren.
Der Kernel wurde von inkrementellen Verknüpfungen zu Thin Archiven in Version 4.9 verschoben, wie unter https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624 beschrieben
Vollständige Protokollinterpretation
Wenn wir die ausführlichen Build-Protokolle von Anfang an lesen, sehen wir zuerst:
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
also sind diese beiden nur miteinander verbunden.
Dann suchen wir etwas weiter x86/boot/bzImage
und finden:
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 die Hilfemeldung:
Usage: build setup system zoffset.h image
und grep um die Quelle zu finden:
arch/x86/boot/tools/build.c
Also muss dieses Tool arch/x86/boot/bzImage
aus arch/x86/boot/vmlinux.bin
und anderen Dateien generieren . TODO, worum geht es build
genau?
Wenn wir folgen arch/x86/boot/vmlinux.bin
, sehen wir, dass es nur ein objcopy
von ist 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 reguläre 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, das piggy.o
ist bei weitem die größte Datei, also suchen wir danach und sie muss kommen 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 macht:
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 ls -l
, daher habe ich nach einer neuen ar
Funktion gesucht und gelernt, die ich nicht kannte: dünne Archive.
Beim:
AR built-in.a
Der Build macht:
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 Thin-Archiv an.
Wir können dann sehen, dass alle Unterarchive auch dünn sind, z. B. init/main.c
haben wir seit meiner Änderung :
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
Das kommt schließlich aus der C-Datei durch einen Befehl wie:
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 das nicht finden init/.tmp_main.o
, init/main.o
um auf die Protokolle zu treten, was eine Schande ist ... mit:
git grep '\.tmp_'
wir sehen das kommt wahrscheinlich von scripts Makefile.build
und ist mit dem verbunden CONFIG_MODVERSIONS
was ich aktiviert hatte:
ifndef CONFIG_MODVERSIONS
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
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 $@ $(@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) $@; \
fi;
endif
Analyse mit dieser Konfiguration durchgeführt, die enthält CONFIG_KERNEL_GZIP=y
.
aarch64 arch/arm64/boot/Image
Nur eine unkomprimierte objcopy
von vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
wird im Grunde auf die gleiche Weise wie für x86 durch die dünnen Archive erhalten.
arch/arm/boot/zImage
Sehr ähnlich zu X86 mit einem Reißverschluss vmlinux
, aber ohne Zauberschritt build.c
. Zusammenfassung der Aufrufkette:
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 aber nicht von vmlinux booten
Dies ist ein weiterer wichtiger praktischer Unterschied: https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu