zephyr/scripts/link-zephyr.sh

289 lines
7 KiB
Bash
Raw Normal View History

#!/bin/sh
#
# link the kernel
#
# The kernel is linked from the objects selected by $(KBUILD_ZEPHYR_INIT) and
# $(KBUILD_ZEPHYR_MAIN). Most are built-in.o files from top-level directories
# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
# Ordering when linking is important, and $(KBUILD_ZEPHYR_INIT) must be first.
#
# microkernel/nanokernel
# ^
# |
# +-< $(KBUILD_ZEPHYR_INIT)
# | +--< init/version.o + more
# |
# +--< $(KBUILD_ZEPHYR_MAIN)
# | +--< drivers/built-in.o mm/built-in.o + more
# |
# +-< ${kallsymso} (see description in KALLSYMS section)
#
# Error out on error
set -e
# Nice output in kbuild format
# Will be supressed by "make -s"
info()
{
if [ "${quiet}" != "silent_" ]; then
printf " %-7s %s\n" ${1} ${2}
fi
}
# Creates linker parameters.
# {1} output file
# {2} symbol map file
linker_params()
{
LIBS=""
for tcl in ${ALL_LIBS}; do LIBS="${LIBS} -l${tcl}"; done
echo "${LDFLAGS_zephyr}" > ${1}
echo "-Map ./${2}" >> ${1}
echo "-L ${objtree}/include/generated" >> ${1}
echo "-u _OffsetAbsSyms -u _ConfigAbsSyms" >> ${1}
echo "-e __start" >> ${1}
echo "--start-group ${KBUILD_ZEPHYR_MAIN} ${KBUILD_ZEPHYR_APP}" >> ${1}
echo "${objtree}/include/generated/offsets.o" >> ${1}
echo "--end-group" >> ${1}
echo "${LIB_INCLUDE_DIR} ${LIBS}" >> ${1}
}
#Creates linker command file
# {1} output file
# {2} optional additional link parameters
linker_command()
{
${CC} -x assembler-with-cpp -nostdinc -undef -E -P \
${LDFLAG_LINKERCMD} \
${LD_TOOLCHAIN} ${2} \
-I${srctree}/include -I${objtree}/include/generated \
${KBUILD_LDS} \
-o ${1}
}
# Link of ${KERNEL_NAME}.o used for section mismatch analysis
# ${1} output file
# ${2} linker parameters file
# ${3} linker command file
initial_link()
{
${LD} -T ${3} @${2} -o ${1}
}
#Generates IDT and merge them into final binary
# ${1} input file (${KERNEL_NAME}.elf)
# ${2} output file (staticIdt.o)
gen_idt()
{
toolchain: add support for iamcu toolchain See https://groups.google.com/forum/#!topic/ia32-abi/cn7TM6J_TIg for more details. • Support IA32 without FPU. • Minimum ISA: Pentium ISA without x87 FPU instructions. • Don't allow mixing i386 object files with Intel MCU object files. • Support floating point with software emulation: a. Long double is the same as double. b. Use __float80 for 80-bit double. • Minimize memory footprint: a. Code size b. Data size c. Stack size Here is the draft of Intel MCU psABI. The differences from IA32 psABI are 1. The minimum instruction set is Intel Pentium ISA minus instructions for x87 floating point unit. 2. There are no x87 floating point registers. 3. There are no vector registers. 4. Segment registers are optional. 5. Support for TLS relocations are optional. 6. Scalar types larger than 4 bytes are aligned to 4 bytes. 7. There are no vector types. 8. _Decimal32, _Decimal64, and _Decimal128 types are optional. 9. long double type is the same as double. 10. float, double and long double types are passed and returned in general purpose registers. 11. _Decimal32 and _Decimal64 types are passed in general purpose registers. 12. Aggregate types no larger than 8 bytes are passed and returned in general purpose registers. 13. Stack is 4-byte aligned. 14. The auxiliary vector support is optional. 15. Register %edx has undefined value at process entry. 16. New ELF machine code: EM_IAMCU. 17. New predefined C/C++ pre-processor symbols: __iamcu and __iamcu__ Change-Id: I6a0c45ad22d8f710b6f37a041aaa2fc1bf0b1c39 Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2015-06-19 23:37:23 -04:00
test -z $OUTPUT_FORMAT && OUTPUT_FORMAT=elf32-i386
test -z $OUTPUT_ARCH && OUTPUT_ARCH=i386
${OBJCOPY} -I $OUTPUT_FORMAT -O binary -j intList ${1} isrList.bin
${GENIDT} -i isrList.bin -n ${CONFIG_IDT_NUM_VECTORS:-256} -o staticIdt.bin
toolchain: add support for iamcu toolchain See https://groups.google.com/forum/#!topic/ia32-abi/cn7TM6J_TIg for more details. • Support IA32 without FPU. • Minimum ISA: Pentium ISA without x87 FPU instructions. • Don't allow mixing i386 object files with Intel MCU object files. • Support floating point with software emulation: a. Long double is the same as double. b. Use __float80 for 80-bit double. • Minimize memory footprint: a. Code size b. Data size c. Stack size Here is the draft of Intel MCU psABI. The differences from IA32 psABI are 1. The minimum instruction set is Intel Pentium ISA minus instructions for x87 floating point unit. 2. There are no x87 floating point registers. 3. There are no vector registers. 4. Segment registers are optional. 5. Support for TLS relocations are optional. 6. Scalar types larger than 4 bytes are aligned to 4 bytes. 7. There are no vector types. 8. _Decimal32, _Decimal64, and _Decimal128 types are optional. 9. long double type is the same as double. 10. float, double and long double types are passed and returned in general purpose registers. 11. _Decimal32 and _Decimal64 types are passed in general purpose registers. 12. Aggregate types no larger than 8 bytes are passed and returned in general purpose registers. 13. Stack is 4-byte aligned. 14. The auxiliary vector support is optional. 15. Register %edx has undefined value at process entry. 16. New ELF machine code: EM_IAMCU. 17. New predefined C/C++ pre-processor symbols: __iamcu and __iamcu__ Change-Id: I6a0c45ad22d8f710b6f37a041aaa2fc1bf0b1c39 Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2015-06-19 23:37:23 -04:00
${OBJCOPY} -I binary -B $OUTPUT_ARCH -O $OUTPUT_FORMAT --rename-section .data=staticIdt staticIdt.bin ${2}
rm -f staticIdt.bin
rm -f isrList.bin
}
# Linking the kernel
# ${1} - linker params file (${KERNEL_NAME}.lnk)
# ${2} - linker command file (final-linker.cmd)
# ${3} - input file (staticIdt.o)
# ${4} - output file
zephyr_link()
{
${LD} -T ${2} @${1} ${3} -o ${4}
${OBJCOPY} --set-section-flags intList=noload ${4} elf.tmp
${OBJCOPY} -R intList elf.tmp ${4}
rm elf.tmp
}
zephyr_bin_strip()
{
${OBJDUMP} -S ${1} >${2}
${OBJCOPY} -S -O binary -R .note -R .comment -R COMMON -R .eh_frame ${1} ${3}
${STRIP} -s -o ${4} ${1}
}
# Create ${2} .o file with all symbols from the ${1} object file
kallsyms()
{
info KSYM ${2}
local kallsymopt;
if [ -n "${CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX}" ]; then
kallsymopt="${kallsymopt} --symbol-prefix=_"
fi
if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
kallsymopt="${kallsymopt} --all-symbols"
fi
if [ -n "${CONFIG_ARM}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
fi
if [ -n "${CONFIG_X86_64}" ]; then
kallsymopt="${kallsymopt} --absolute-percpu"
fi
local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
${NOSTDINC_FLAGS} ${ZEPHYRINCLUDE} ${KBUILD_CPPFLAGS}"
${NM} -n ${1} | \
scripts/kallsyms ${kallsymopt} | \
${CC} ${aflags} -c -o ${2} -x assembler-with-cpp -
}
# Create map file with all symbols from ${1}
# See mksymap for additional details
mksysmap()
{
${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
}
sortextable()
{
${objtree}/scripts/sortextable ${1}
}
# Delete output files in case of error
trap cleanup SIGHUP SIGINT SIGQUIT SIGTERM ERR
cleanup()
{
rm -f .old_version
rm -f .tmp_System.map
rm -f .tmp_kallsyms*
rm -f .tmp_version
rm -f .tmp_*
rm -f System.map
rm -f *.lnk
rm -f *.map
rm -f *.elf
rm -f *.lst
rm -f *.bin
rm -f *.strip
rm -f staticIdt.o
rm -f linker.cmd
rm -f final-linker.cmd
}
#
#
# Use "make V=1" to debug this script
case "${KBUILD_VERBOSE}" in
*1*)
set -x
;;
esac
if [ "$1" = "clean" ]; then
cleanup
exit 0
fi
# We need access to CONFIG_ symbols
case "${KCONFIG_CONFIG}" in
*/*)
. "${KCONFIG_CONFIG}"
;;
*)
# Force using a file from the current directory
. "./${KCONFIG_CONFIG}"
esac
#link ${KERNEL_NAME}.o
info LD ${KERNEL_NAME}.elf
linker_params ${KERNEL_NAME}.lnk ${KERNEL_NAME}.map
linker_command linker.cmd
initial_link ${KERNEL_NAME}.elf ${KERNEL_NAME}.lnk linker.cmd
# Update version
info GEN .version
if [ ! -r .version ]; then
rm -f .version;
echo 1 >.version;
else
mv .version .old_version;
expr 0$(cat .old_version) + 1 >.version;
fi;
kallsymso=""
kallsyms_zephyr=""
if [ -n "${CONFIG_KALLSYMS}" ]; then
# kallsyms support
# Generate section listing all symbols and add it into the kernel
# It's a three step process:
# 1) Link .tmp_${KERNEL_NAME} so it has all symbols and sections,
# but __kallsyms is empty.
# Running kallsyms on that gives us .tmp_kallsyms1.o with
# the right size
# 2) Link .tmp_${KERNEL_NAME}2 so it now has a __kallsyms section of
# the right size, but due to the added section, some
# addresses have shifted.
# From here, we generate a correct .tmp_kallsyms2.o
# 2a) We may use an extra pass as this has been necessary to
# woraround some alignment related bugs.
# KALLSYMS_EXTRA_PASS=1 is used to trigger this.
# 3) The correct ${kallsymso} is linked into the final kernel.
#
# a) Verify that the System.map matches the map from
# ${kallsymso}.
kallsymso=.tmp_kallsyms2.o
kallsyms_zephyr=.tmp_${KERNEL_NAME}2
# step 1
zephyr_link "" .tmp_${KERNEL_NAME}1
kallsyms .tmp_${KERNEL_NAME}1 .tmp_kallsyms1.o
# step 2
zephyr_link .tmp_kallsyms1.o .tmp_${KERNEL_NAME}2
kallsyms .tmp_${KERNEL_NAME}2 .tmp_kallsyms2.o
# step 2a
if [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
kallsymso=.tmp_kallsyms3.o
kallsyms_zephyr=.tmp_${KERNEL_NAME}3
zephyr_link .tmp_kallsyms2.o .tmp_${KERNEL_NAME}3
kallsyms .tmp_${KERNEL_NAME}3 .tmp_kallsyms3.o
fi
fi
if [ "${SRCARCH}" = "x86" ]; then
info SIDT ${KERNEL_NAME}.elf
gen_idt ${KERNEL_NAME}.elf staticIdt.o
linker_command final-linker.cmd -DFINAL_LINK
zephyr_link ${KERNEL_NAME}.lnk final-linker.cmd staticIdt.o ${KERNEL_NAME}.elf
fi
info BIN ${KERNEL_NAME}.bin
zephyr_bin_strip ${KERNEL_NAME}.elf ${KERNEL_NAME}.lst ${KERNEL_NAME}.bin ${KERNEL_NAME}.strip
if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
info SORTEX ${KERNEL_NAME}
sortextable ${KERNEL_NAME}
fi
info SYSMAP System.map
mksysmap ${KERNEL_NAME}.elf System.map
# step a (see comment above)
if [ -n "${CONFIG_KALLSYMS}" ]; then
mksysmap ${kallsyms_zephyr} .tmp_System.map
if ! cmp -s System.map .tmp_System.map; then
echo >&2 Inconsistent kallsyms data
echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
cleanup
exit 1
fi
fi
# We made a new kernel - delete old version file
rm -f .old_version