vmlinux
Toto je linuxové jádro ve staticky propojeném formátu spustitelného souboru. Obecně se o tento soubor nemusíte starat, je to jen mezikrok při zavádění.
Nezpracovaný soubor vmlinux může být užitečný pro účely ladění.
vmlinux.bin
Stejné jako vmlinux, ale ve formátu bootovatelného surového binárního souboru. Všechny symboly a informace o přemístění jsou vyřazeny. Vygenerováno z vmlinux
podle objcopy -O binary vmlinux vmlinux.bin
.
vmlinuz
Soubor vmlinux se obvykle komprimuje pomocí zlib
. Od 2.6.30 LZMA
a bzip2
jsou také k dispozici. Přidáním dalších možností zavádění a dekomprese do vmlinuz lze obraz použít k zavedení systému s jádrem vmlinux. Komprese vmlinuxu může probíhat pomocí zImage nebo bzImage.
Funkce decompress_kernel()
zpracovává dekompresi vmlinuz při bootování, zpráva ukazuje toto:
Decompressing Linux... done
Booting the kernel.
zImage (make zImage
)
Toto je starý formát pro malá jádra (komprimovaný, pod 512 kB). Při spouštění se tento obraz načte málo v paměti (prvních 640 kB paměti RAM).
bzImage (make bzImage
)
Velký zImage (to nemá nic společného s bzip2
), byl vytvořen, zatímco jádro rostlo a zpracovává větší obrázky (komprimované, přes 512 kB). Obrázek se načte vysoko v paměti (nad 1 MB RAM). Protože dnešní jádra mají mnohem více než 512 kB, je to obvykle preferovaný způsob.
Kontrola na Ubuntu 10.10 ukazuje:
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
Proveďte podrobné sestavení jádra a vyhledejte soubory
Tento přístup může poskytnout určitý přehled, nikdy nezestárne a pomůže vám snadno zjistit, která část systému sestavení co dělá.
Jakmile budete mít konfiguraci sestavení, která generuje jeden ze souborů, sestavte pomocí:
make V=1 |& tee f.log
Upravte komentář k některému souboru C, abyste vynutili opětovné propojení (např. init/main.c
je dobrý), pokud jste již dříve stavěli.
Nyní zkontrolujte f.log
a vyhledejte obrázky, které vás zajímají.
Například ve verzi 4.19 dojdeme k závěru, že:
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
Tenké archivy jsou zmíněny na:https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Jsou to archivy, které pouze ukazují na jiné archivy/objekty, místo aby je kopírovaly.
Jádro se ve verzi 4.9 přesunulo z inkrementálního linkování na tenké archivy, jak je popsáno na:https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
Úplná interpretace protokolu
Když začneme číst podrobné protokoly sestavení odzadu nahoru, nejprve uvidíme:
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
takže tito dva jsou jen symbolicky propojeni.
Pak hledáme o něco dále x86/boot/bzImage
a najděte:
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
je spustitelný soubor, takže jej spustíme, viz zpráva nápovědy:
Usage: build setup system zoffset.h image
a grep k nalezení zdroje:
arch/x86/boot/tools/build.c
Tento nástroj tedy musí generovat arch/x86/boot/bzImage
od arch/x86/boot/vmlinux.bin
a další soubory TODO jaký je smysl build
přesně?
Pokud budeme postupovat podle arch/x86/boot/vmlinux.bin
vidíme, že je to jen objcopy
od arch/x86/boot/compressed/vmlinux
:
objcopy \
-O binary \
-R .note \
-R .comment \
-S arch/x86/boot/compressed/vmlinux \
arch/x86/boot/vmlinux.bin
a arch/x86/boot/compressed/vmlinux
je pouze běžný soubor ELF:
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
říká, že piggy.o
je zdaleka největší soubor, takže jej hledáme a musí pocházet z:
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_
prefix vysvětlený níže.
arch/x86/boot/compressed/piggy.S
obsahuje:
.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"
viz také:https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692
arch/x86/boot/compressed/vmlinux.bin.gz
pochází z:
cat arch/x86/boot/compressed/vmlinux.bin arch/x86/boot/compressed/vmlinux.relocs | \
gzip -n -f -9 > arch/x86/boot/compressed/vmlinux.bin.gz
který pochází z:
objcopy -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin
který pochází z:
LD vmlinux
což dělá:
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
je obrovský, ale všechny zobrazené objekty jsou podle ls -l
malé , tak jsem prozkoumal a dozvěděl se o novém ar
funkce, o které jsem nevěděl:tenké archivy.
V:
AR built-in.a
sestava dělá:
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
určuje tenký archiv.
Pak můžeme vidět, že všechny dílčí archivy jsou také tenké, např. protože jsem upravil init/main.c
, máme:
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
který nakonec pochází ze souboru C pomocí příkazu jako:
gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c
Nemohu najít init/.tmp_main.o
na init/main.o
šlápnout na klády, což je škoda... s:
git grep '\.tmp_'
vidíme, že pravděpodobně pochází z scripts Makefile.build
a je propojen s CONFIG_MODVERSIONS
které jsem povolil:
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
Analýza provedena s touto konfigurací, která obsahuje CONFIG_KERNEL_GZIP=y
.
aarch64 arch/arm64/boot/Image
Pouze nekomprimovaný objcopy
z vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
se získává v podstatě úplně stejným způsobem jako pro x86 přes tenké archivy.
arch/arm/boot/zImage
Velmi podobné X86 se zazipovaným vmlinux
, ale žádné kouzlo build.c
krok. Shrnutí řetězce hovorů:
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 může bootovat z bzImage, ale ne vmlinux
Toto je další důležitý praktický rozdíl:https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu