Skip to contentSkip to conversation

ARM: decompressor: fix BSS size calculation

PATCH New Russell King 1 participant 1 message Sep 25, 2017 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ARM: decompressor: fix BSS size calculation

Assuming size(1) gives the size of the BSS is a mistake - it reports the size of the .bss section in the ELF image, which may not be the same as the region we mark with the __bss_start..__bss_stop symbols.

We use the size of the BSS in the decompressor to know whether the kernel will overwrite the appended dtb, by adding the BSS size to the size of the Image (stored at the end of the compressed data) and adding the desired address of the decompressed image.

If the BSS size is smaller than it really is, the decompressor can incorrectly assume that the BSS clearance will not overwrite the DTB.

Here is an illustration:

$ arm-linux-size vmlinux
   text    data      bss      dec     hex filename
8136972 3098076 10240348 21475396 147b044 vmlinux
$ arm-linux-nm vmlinux | grep __bss_
c0ac0e34 B __bss_start
c1484f9c B __bss_stop
$ stat -c %s arch/arm/boot/Image
11243060

In the above case, we are 12 bytes short. This is caused by the BSS section being aligned by one of its input sections:

Idx Name          Size      VMA       LMA       File off  Algn
 23 __bug_table   00005d3c  c0abb0f8  c0abb0f8  00acb0f8  2**2

CONTENTS, ALLOC, LOAD, DATA
24 .bss 009c415c c0ac0e40 c0ac0e40 00ad0e34 2**6
ALLOC

Note that there's an additional 12 bytes difference between the file offset and LMA compared with the bug table - this occurs because one of the input sections for the .bss section requires a 64 byte alignment.

Fix this by using 'nm' and awk to access the __bss_start and __bss_stop symbols, using their difference for the size of the BSS.

---
 arch/arm/boot/compressed/Makefile | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/arm/boot/compressed/Makefile +4 -2
index d50430c40045..d26e250a56b0 100644
@@ -116,8 +116,10 @@ ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
 asflags-y := -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
-KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \
-		awk 'END{print $$3}')
+KBSS_SZ = $(shell $(CROSS_COMPILE)nm $(obj)/../../../../vmlinux | \
+		awk '/B __bss_start$$/ {bss_start=strtonum("0x"$$1)}; \
+		     /B __bss_stop$$/ {bss_stop=strtonum("0x"$$1)}; \
+		     END {print bss_stop-bss_start}')
 LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
 # Supply ZRELADDR to the decompressor via a linker symbol.
 ifneq ($(CONFIG_AUTO_ZRELADDR),y)
Signature · 1 line
2.7.4