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.ceine gute), wenn Sie diese bereits zuvor erstellt haben.
Überprüfen Sie nun die gewünschten f.logBilder 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/bzImageund 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/bzImageaus arch/x86/boot/vmlinux.binund anderen Dateien generieren . TODO, worum geht es buildgenau?
Wenn wir folgen arch/x86/boot/vmlinux.bin, sehen wir, dass es nur ein objcopyvon 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/vmlinuxist 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 -hlSrsagt, das piggy.oist 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
vmlinuxist riesig, aber alle gezeigten Objekte sind winzig ls -l, daher habe ich nach einer neuen arFunktion 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.chaben 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.oum auf die Protokolle zu treten, was eine Schande ist ... mit:
git grep '\.tmp_'
wir sehen das kommt wahrscheinlich von scripts Makefile.buildund ist mit dem verbunden CONFIG_MODVERSIONSwas 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 objcopyvon 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