Thực hiện xây dựng nhân dài dòng và tìm kiếm các tệp
Cách tiếp cận này có thể cung cấp một số cái nhìn sâu sắc, sẽ không bao giờ lỗi thời và sẽ giúp bạn dễ dàng tìm thấy phần nào của hệ thống xây dựng đang làm gì.
Khi bạn có cấu hình bản dựng tạo một trong các tệp, hãy tạo với:
make V=1 |& tee f.log
Sửa đổi nhận xét về một số tệp C để buộc liên kết lại (ví dụ: init/main.c
một liên kết tốt) nếu bạn đã xây dựng trước đó.
Bây giờ, kiểm tra f.log
và tìm kiếm những hình ảnh quan tâm.
Ví dụ, vào v4.19, chúng tôi sẽ kết luận rằng:
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
Tài liệu lưu trữ mỏng được đề cập tại: https://stackoverflow.com/questions/2157629/linking-static-lologists-to-other-static-lologists/27676016#27676016 Chúng là những tài liệu lưu trữ chỉ trỏ các tài liệu lưu trữ / đối tượng khác thay vì sao chép chúng.
Hạt nhân đã chuyển từ liên kết gia tăng sang tài liệu lưu trữ mỏng trong v4.9 như được mô tả tại: https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
Giải thích nhật ký đầy đủ
Khi chúng ta bắt đầu đọc nhật ký xây dựng dài dòng từ bản sao lưu, đầu tiên chúng ta sẽ thấy:
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
vì vậy hai cái đó chỉ là liên kết với nhau
Sau đó, chúng tôi tìm kiếm thêm một chút cho x86/boot/bzImage
và tìm:
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
là một tệp thực thi, vì vậy chúng tôi chạy nó, xem thông báo trợ giúp:
Usage: build setup system zoffset.h image
và grep để tìm nguồn:
arch/x86/boot/tools/build.c
Vì vậy, công cụ này phải được tạo arch/x86/boot/bzImage
từ arch/x86/boot/vmlinux.bin
và các tệp khác TODO điểm build
chính xác là gì?
Nếu chúng tôi theo dõi, arch/x86/boot/vmlinux.bin
chúng tôi thấy rằng đó chỉ là một objcopy
từ arch/x86/boot/compressed/vmlinux
:
objcopy \
-O binary \
-R .note \
-R .comment \
-S arch/x86/boot/compressed/vmlinux \
arch/x86/boot/vmlinux.bin
và arch/x86/boot/compressed/vmlinux
chỉ là một tệp ELF thông thường:
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
nói rằng đó piggy.o
là tập tin lớn nhất, vì vậy chúng tôi tìm kiếm nó và nó phải đến từ:
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_
tiền tố giải thích dưới đây.
arch/x86/boot/compressed/piggy.S
chứa đựng:
.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"
xem thêm: https://stackoverflow.com/questions/4158900/embpping-resource-in-executable-USE-gcc/36295692#36295692
arch/x86/boot/compressed/vmlinux.bin.gz
đến từ:
cat arch/x86/boot/compressed/vmlinux.bin arch/x86/boot/compressed/vmlinux.relocs | \
gzip -n -f -9 > arch/x86/boot/compressed/vmlinux.bin.gz
xuất phát từ:
objcopy -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin
xuất phát từ:
LD vmlinux
cái nào:
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
là rất lớn, nhưng tất cả các đối tượng được hiển thị đều nhỏ bé ls -l
, vì vậy tôi đã nghiên cứu và tìm hiểu về một ar
tính năng mới mà tôi không biết: lưu trữ mỏng.
Tại:
AR built-in.a
bản dựng không:
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
chỉ định lưu trữ mỏng.
Sau đó chúng ta có thể thấy rằng tất cả các tài liệu lưu trữ phụ cũng mỏng, ví dụ, kể từ khi tôi sửa đổi init/main.c
, chúng ta có:
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
mà cuối cùng xuất phát từ tệp C thông qua một lệnh như:
gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c
Tôi không thể tìm ra init/.tmp_main.o
để init/main.o
bước vào các bản ghi đó là một sự xấu hổ ... với:
git grep '\.tmp_'
chúng tôi thấy rằng có khả năng đến từ scripts Makefile.build
và được liên kết với CONFIG_MODVERSIONS
mà tôi đã kích hoạt:
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
Phân tích được thực hiện với cấu hình này có chứa CONFIG_KERNEL_GZIP=y
.
aarch64 arch/arm64/boot/Image
Chỉ là một giải nén objcopy
từ vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
về cơ bản được lấy theo cách chính xác giống như đối với x86 mặc dù tài liệu lưu trữ mỏng.
arch/arm/boot/zImage
Rất giống với X86 với khóa kéo vmlinux
, nhưng không có build.c
bước ma thuật . Tóm tắt chuỗi cuộc gọi:
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 có thể khởi động từ bzImage nhưng không phải vmlinux
Đây là một sự khác biệt thực tế quan trọng khác: https://superuser.com/questions/1451568/boote-an-uncompression-kernel-in-qemu