Lakukan pembuatan kernel verbose dan cari file
Pendekatan ini dapat memberikan beberapa wawasan, tidak akan pernah ketinggalan zaman, dan akan membantu Anda untuk dengan mudah menemukan bagian mana dari sistem build yang melakukan apa.
Setelah Anda memiliki konfigurasi build yang menghasilkan salah satu file, build with:
make V=1 |& tee f.log
Ubah komentar pada beberapa file C untuk memaksa tautan ulang (mis. Yang init/main.c
bagus) jika Anda sudah membangun sebelumnya.
Sekarang, periksa f.log
dan cari gambar yang menarik.
Sebagai contoh, pada v4.19 kita akan menyimpulkan bahwa:
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
Arsip tipis disebutkan di: https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Ini adalah arsip yang hanya menunjuk arsip / objek lain alih-alih menyalinnya.
Kernel bergerak dari penautan bertahap ke arsip tipis di v4.9 seperti dijelaskan di: https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
Interpretasi log lengkap
Ketika kita mulai membaca log build verbose dari belakang, pertama-tama kita melihat:
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
jadi keduanya hanya disinkronkan.
Kemudian kami mencari sedikit lebih jauh x86/boot/bzImage
dan menemukan:
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
dapat dieksekusi, jadi kami jalankan, lihat pesan bantuan:
Usage: build setup system zoffset.h image
dan grep untuk menemukan sumbernya:
arch/x86/boot/tools/build.c
Jadi alat ini harus menghasilkan arch/x86/boot/bzImage
dari arch/x86/boot/vmlinux.bin
dan file-file lain TODO apa gunanya build
sebenarnya?
Jika kita mengikuti, arch/x86/boot/vmlinux.bin
kita melihat bahwa itu hanya objcopy
dari arch/x86/boot/compressed/vmlinux
:
objcopy \
-O binary \
-R .note \
-R .comment \
-S arch/x86/boot/compressed/vmlinux \
arch/x86/boot/vmlinux.bin
dan arch/x86/boot/compressed/vmlinux
ini hanya file ELF biasa:
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
mengatakan itu piggy.o
adalah file terbesar, jadi kami mencarinya, dan itu harus berasal dari:
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_
awalan dijelaskan di bawah ini.
arch/x86/boot/compressed/piggy.S
mengandung:
.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"
lihat juga: https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692
arch/x86/boot/compressed/vmlinux.bin.gz
datang dari:
cat arch/x86/boot/compressed/vmlinux.bin arch/x86/boot/compressed/vmlinux.relocs | \
gzip -n -f -9 > arch/x86/boot/compressed/vmlinux.bin.gz
yang berasal dari:
objcopy -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin
yang berasal dari:
LD vmlinux
yang tidak:
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
memang besar, tetapi semua objek yang ditampilkan kecil menurut ls -l
, jadi saya meneliti dan mempelajari ar
fitur baru yang tidak saya ketahui: arsip tipis.
Di:
AR built-in.a
build tidak:
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
menentukan arsip tipis.
Kita kemudian dapat melihat bahwa semua sub arsip juga tipis, misalnya, karena saya modifikasi init/main.c
, kami memiliki:
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
yang akhirnya berasal dari file C melalui perintah seperti:
gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c
Saya tidak dapat menemukan init/.tmp_main.o
untuk init/main.o
menginjak log yang memalukan ... dengan:
git grep '\.tmp_'
kami melihat bahwa kemungkinan berasal dari scripts Makefile.build
dan terhubung dengan CONFIG_MODVERSIONS
yang telah saya aktifkan:
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
Analisis dilakukan dengan konfigurasi ini yang berisi CONFIG_KERNEL_GZIP=y
.
aarch64 arch/arm64/boot/Image
Hanya yang tidak dikompresi objcopy
dari vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
diperoleh pada dasarnya dengan cara yang sama persis seperti untuk x86 meskipun arsip tipis.
arch/arm/boot/zImage
Sangat mirip dengan X86 dengan zip vmlinux
, tetapi tidak ada build.c
langkah ajaib . Ringkasan rantai panggilan:
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 dapat melakukan boot dari bzImage tetapi tidak vmlinux
Ini adalah perbedaan praktis penting lainnya: https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu