From 31333ebb9964e2ef53af143498639ec67f4ae40a Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Sun, 29 Dec 2019 18:17:12 +0000 Subject: [PATCH] Eliminate the generated ldscript for arm and arm64, and strip $a/$d marker symbols from the linked kernel. The main thrust of this change is to generate a kernel that has the arm "marker" symbols stripped. Marker symbols start with $a, $d, $t or $x, and are emitted by the compiler to tell other toolchain components about the locations of data embedded in the instruction stream (literal-pool stuff). They are used for generating mixed-endian binaries (which we don't support). The linked kernel has approximately 21,000 such symbols in it, wasting space (500K in kernel.full, 190K in the final linked kernel), and sometimes obscuring function names in stack tracebacks. This change also simplifies the way the kernel is linked. Instead of using sed to generate two different ldscript files to generate both an elf kernel and a binary (elf headers stripped) kernel, we now use a single ldscript that refers to a "text_start" symbol, and we provide the value for that symbol using --defsym on the linker command line. --- sys/conf/Makefile.arm | 51 ++++++++++++++++++++++++++--------------- sys/conf/Makefile.arm64 | 46 ++++++++++++++++++++++++++----------- sys/conf/ldscript.arm | 2 +- sys/conf/ldscript.arm64 | 2 +- 4 files changed, 67 insertions(+), 34 deletions(-) diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm index e981fa697608..0e80fc0575d2 100644 --- a/sys/conf/Makefile.arm +++ b/sys/conf/Makefile.arm @@ -32,9 +32,6 @@ S= ../../.. INCLUDES+= -I$S/contrib/libfdt -I$S/gnu/dts/include -SYSTEM_LD:= ${SYSTEM_LD:$S/conf/ldscript.$M=ldscript.$M} -SYSTEM_DEP:= ${SYSTEM_DEP:$S/conf/ldscript.$M=ldscript.$M} - .if !defined(DEBUG) && !defined(PROFLEVEL) STRIP_FLAGS = -S .endif @@ -58,20 +55,41 @@ CFLAGS += -mllvm -arm-enable-ehabi KERNVIRTADDR= 0xc0000000 .endif +# Use a custom SYSTEM_LD command to generate the elf kernel, so we can +# set the text segment start address, and also strip the "arm mapping +# symbols" which have names like $a.0 and $d.2; see the document +# "ELF for the ARM architecture" for more info on the mapping symbols. +SYSTEM_LD= \ + ${SYSTEM_LD_BASECMD} \ + --defsym='text_start=${KERNVIRTADDR} + SIZEOF_HEADERS' \ + -o ${.TARGET} ${SYSTEM_OBJS} vers.o; \ + $(OBJCOPY) \ + --wildcard \ + --strip-symbol='$$[adt]*' \ + ${.TARGET} + +# Generate the .bin (no elf headers) kernel as an extra build output. +# We must relink to generate the .bin kernel, because without headers the +# location of everything changes. We also strip the ARM marker symbols. +KERNEL_EXTRA+= ${KERNEL_KO}.bin +KERNEL_EXTRA_INSTALL+= ${KERNEL_KO}.bin + +${KERNEL_KO}.bin: ${SYSTEM_DEP} vers.o + @echo "linking ${.TARGET}" + @${SYSTEM_LD_BASECMD} \ + --defsym='text_start=${KERNVIRTADDR}' \ + -o ${.TARGET} ${SYSTEM_OBJS} vers.o + ${SIZE} ${.TARGET} + @${OBJCOPY} \ + --wildcard \ + --strip-symbol='$$[adt]*' \ + --output-target=binary \ + ${.TARGET} + @chmod 755 ${.TARGET} + # hack because genassym.c includes sys/bus.h which includes these. genassym.o: bus_if.h device_if.h -SYSTEM_LD_ = ${LD} -m ${LD_EMULATION} -Bdynamic -T ldscript.$M.noheader \ - ${_LDFLAGS} --no-warn-mismatch --warn-common --export-dynamic \ - --dynamic-linker /red/herring \ - -o ${FULLKERNEL}.noheader -X ${SYSTEM_OBJS} vers.o -SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// ldscript.$M \ - >ldscript.$M.noheader; \ - ${SYSTEM_LD_}; \ - ${OBJCOPY} -S -O binary ${FULLKERNEL}.noheader \ - ${KERNEL_KO}.bin; \ - rm ${FULLKERNEL}.noheader - %BEFORE_DEPEND %OBJS @@ -84,10 +102,7 @@ SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// ldscript.$M \ %CLEAN -CLEAN+= ldscript.$M ${KERNEL_KO}.bin ldscript.$M.noheader - -ldscript.$M: $S/conf/ldscript.$M - sed s/KERNVIRTADDR/${KERNVIRTADDR}/g > ldscript.$M < $S/conf/ldscript.$M +CLEAN+= ${KERNEL_KO}.bin %RULES diff --git a/sys/conf/Makefile.arm64 b/sys/conf/Makefile.arm64 index e0c803b402f1..057f4feb3d38 100644 --- a/sys/conf/Makefile.arm64 +++ b/sys/conf/Makefile.arm64 @@ -27,24 +27,42 @@ S= ../../.. INCLUDES+= -I$S/contrib/libfdt -#SYSTEM_LD:= ${SYSTEM_LD:$S/conf/ldscript.$M=ldscript.$M} -#SYSTEM_DEP:= ${SYSTEM_DEP:$S/conf/ldscript.$M=ldscript.$M} +# Use a custom SYSTEM_LD command to generate the elf kernel, so we can +# set the text segment start address, and also strip the "arm mapping +# symbols" which have names like $a.0 and $d.2; see the document +# "ELF for the ARM architecture" for more info on the mapping symbols. +SYSTEM_LD= \ + ${SYSTEM_LD_BASECMD} \ + --defsym='text_start=kernbase + SIZEOF_HEADERS' \ + -o ${.TARGET} ${SYSTEM_OBJS} vers.o; \ + $(OBJCOPY) \ + --wildcard \ + --strip-symbol='$$[adtx]*' \ + ${.TARGET} + +# Generate the .bin (no elf headers) kernel as an extra build output. +# We must relink to generate the .bin kernel, because without headers the +# location of everything changes. We also strip the ARM marker symbols. +KERNEL_EXTRA+= ${KERNEL_KO}.bin +KERNEL_EXTRA_INSTALL+= ${KERNEL_KO}.bin + +${KERNEL_KO}.bin: ${SYSTEM_DEP} vers.o + @echo "linking ${.TARGET}" + @${SYSTEM_LD_BASECMD} \ + --defsym='text_start=kernbase' \ + -o ${.TARGET} ${SYSTEM_OBJS} vers.o + ${SIZE} ${.TARGET} + @${OBJCOPY} \ + --wildcard \ + --strip-symbol='$$[adtx]*' \ + --output-target=binary \ + ${.TARGET} + @chmod 755 ${.TARGET} .if !empty(DDB_ENABLED) CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer .endif -SYSTEM_LD_ = ${LD} -m ${LD_EMULATION} -Bdynamic -T ldscript.$M.noheader \ - ${_LDFLAGS} --no-warn-mismatch --warn-common --export-dynamic \ - --dynamic-linker /red/herring \ - -o ${FULLKERNEL}.noheader -X ${SYSTEM_OBJS} vers.o -SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// $(LDSCRIPT)\ - >ldscript.$M.noheader;\ - ${SYSTEM_LD_}; \ - ${OBJCOPY} -S -O binary ${FULLKERNEL}.noheader \ - ${KERNEL_KO}.bin; \ - rm ${FULLKERNEL}.noheader - %BEFORE_DEPEND %OBJS @@ -56,7 +74,7 @@ SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// $(LDSCRIPT)\ %FILES.m %CLEAN -CLEAN+= ldscript.$M ${KERNEL_KO}.bin ldscript.$M.noheader +CLEAN+= ${KERNEL_KO}.bin %RULES diff --git a/sys/conf/ldscript.arm b/sys/conf/ldscript.arm index c6e801e875f2..822b3c0775bf 100644 --- a/sys/conf/ldscript.arm +++ b/sys/conf/ldscript.arm @@ -6,7 +6,7 @@ SEARCH_DIR(/usr/lib); SECTIONS { /* Read-only sections, merged into text segment: */ - . = KERNVIRTADDR + SIZEOF_HEADERS; + . = text_start; /* This is set using --defsym= on the command line. */ .text : { *(.text) diff --git a/sys/conf/ldscript.arm64 b/sys/conf/ldscript.arm64 index ae99e4968f34..36af34589db9 100644 --- a/sys/conf/ldscript.arm64 +++ b/sys/conf/ldscript.arm64 @@ -6,7 +6,7 @@ SEARCH_DIR(/usr/lib); SECTIONS { /* Read-only sections, merged into text segment: */ - . = kernbase + SIZEOF_HEADERS; + . = text_start; /* This is set using --defsym= on the command line. */ .text : { *(.text)