From 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:46:07 +0000 Subject: [PATCH] add audio --- kernel/scripts/link-vmlinux.sh | 349 +++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 225 insertions(+), 124 deletions(-) diff --git a/kernel/scripts/link-vmlinux.sh b/kernel/scripts/link-vmlinux.sh index c67daa7..2631ab4 100755 --- a/kernel/scripts/link-vmlinux.sh +++ b/kernel/scripts/link-vmlinux.sh @@ -3,22 +3,17 @@ # # link vmlinux # -# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_INIT) and -# $(KBUILD_VMLINUX_MAIN) and $(KBUILD_VMLINUX_LIBS). Most are built-in.a files -# from top-level directories in the kernel tree, others are specified in -# arch/$(ARCH)/Makefile. Ordering when linking is important, and -# $(KBUILD_VMLINUX_INIT) must be first. $(KBUILD_VMLINUX_LIBS) are archives -# which are linked conditionally (not within --whole-archive), and do not -# require symbol indexes added. +# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_OBJS) and +# $(KBUILD_VMLINUX_LIBS). Most are built-in.a files from top-level directories +# in the kernel tree, others are specified in arch/$(ARCH)/Makefile. +# $(KBUILD_VMLINUX_LIBS) are archives which are linked conditionally +# (not within --whole-archive), and do not require symbol indexes added. # # vmlinux # ^ # | -# +-< $(KBUILD_VMLINUX_INIT) -# | +--< init/version.o + more -# | -# +--< $(KBUILD_VMLINUX_MAIN) -# | +--< drivers/built-in.a mm/built-in.a + more +# +--< $(KBUILD_VMLINUX_OBJS) +# | +--< init/built-in.a drivers/built-in.a mm/built-in.a + more # | # +--< $(KBUILD_VMLINUX_LIBS) # | +--< lib/lib.a + more @@ -35,64 +30,42 @@ # Error out on error set -e +LD="$1" +KBUILD_LDFLAGS="$2" +LDFLAGS_vmlinux="$3" + # Nice output in kbuild format # Will be supressed by "make -s" info() { if [ "${quiet}" != "silent_" ]; then - printf " %-7s %s\n" ${1} ${2} + printf " %-7s %s\n" "${1}" "${2}" fi } -# Thin archive build here makes a final archive with symbol table and indexes -# from vmlinux objects INIT and MAIN, which can be used as input to linker. -# KBUILD_VMLINUX_LIBS archives should already have symbol table and indexes -# added. -# -# Traditional incremental style of link does not require this step -# -# built-in.a output file -# -archive_builtin() +# Generate a linker script to ensure correct ordering of initcalls. +gen_initcalls() { - info AR built-in.a - rm -f built-in.a; - ${AR} rcsTP${KBUILD_ARFLAGS} built-in.a \ - ${KBUILD_VMLINUX_INIT} \ - ${KBUILD_VMLINUX_MAIN} + info GEN .tmp_initcalls.lds - # rebuild with llvm-ar to update the symbol table - if [ -n "${CONFIG_LTO_CLANG}" ]; then - mv -f built-in.a built-in.a.tmp - ${LLVM_AR} rcsT${KBUILD_ARFLAGS} built-in.a $(${AR} t built-in.a.tmp) - rm -f built-in.a.tmp - fi + ${PYTHON} ${srctree}/scripts/jobserver-exec \ + ${PERL} ${srctree}/scripts/generate_initcall_order.pl \ + ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \ + > .tmp_initcalls.lds } -# If CONFIG_LTO_CLANG is selected, generate a linker script to ensure correct -# ordering of initcalls, and with CONFIG_MODVERSIONS also enabled, collect the -# previously generated symbol versions into the same script. -lto_lds() +# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into +# .tmp_symversions.lds +gen_symversions() { - if [ -z "${CONFIG_LTO_CLANG}" ]; then - return - fi + info GEN .tmp_symversions.lds + rm -f .tmp_symversions.lds - ${srctree}/scripts/generate_initcall_order.pl \ - built-in.a ${KBUILD_VMLINUX_LIBS} \ - > .tmp_lto.lds - - if [ -n "${CONFIG_MODVERSIONS}" ]; then - for a in built-in.a ${KBUILD_VMLINUX_LIBS}; do - for o in $(${AR} t $a); do - if [ -f ${o}.symversions ]; then - cat ${o}.symversions >> .tmp_lto.lds - fi - done - done - fi - - echo "-T .tmp_lto.lds" + for o in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do + if [ -f ${o}.symversions ]; then + cat ${o}.symversions >> .tmp_symversions.lds + fi + done } # Link of vmlinux.o used for section mismatch analysis @@ -100,72 +73,139 @@ modpost_link() { local objects + local lds="" objects="--whole-archive \ - built-in.a \ + ${KBUILD_VMLINUX_OBJS} \ --no-whole-archive \ --start-group \ ${KBUILD_VMLINUX_LIBS} \ --end-group" if [ -n "${CONFIG_LTO_CLANG}" ]; then + gen_initcalls + lds="-T .tmp_initcalls.lds" + + if [ -n "${CONFIG_MODVERSIONS}" ]; then + gen_symversions + lds="${lds} -T .tmp_symversions.lds" + fi + # This might take a while, so indicate that we're doing # an LTO link - info LTO vmlinux.o + info LTO ${1} + else + info LD ${1} fi - ${LD} ${KBUILD_LDFLAGS} -r -o ${1} $(lto_lds) ${objects} + ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects} } -# If CONFIG_LTO_CLANG is selected, we postpone running recordmcount until -# we have compiled LLVM IR to an object file. -recordmcount() +objtool_link() { - if [ -z "${CONFIG_LTO_CLANG}" ]; then - return + local objtoolcmd; + local objtoolopt; + + if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then + # Don't perform vmlinux validation unless explicitly requested, + # but run objtool on vmlinux.o now that we have an object file. + if [ -n "${CONFIG_UNWINDER_ORC}" ]; then + objtoolcmd="orc generate" + fi + + objtoolopt="${objtoolopt} --duplicate" + + if [ -n "${CONFIG_FTRACE_MCOUNT_USE_OBJTOOL}" ]; then + objtoolopt="${objtoolopt} --mcount" + fi fi - if [ -n "${CONFIG_FTRACE_MCOUNT_RECORD}" ]; then - scripts/recordmcount ${RECORDMCOUNT_FLAGS} $* + if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then + objtoolopt="${objtoolopt} --noinstr" + fi + + if [ -n "${objtoolopt}" ]; then + if [ -z "${objtoolcmd}" ]; then + objtoolcmd="check" + fi + objtoolopt="${objtoolopt} --vmlinux" + if [ -n "${CONFIG_CPU_UNRET_ENTRY}" ]; then + objtoolopt="${objtoolopt} --unret" + fi + if [ -z "${CONFIG_FRAME_POINTER}" ]; then + objtoolopt="${objtoolopt} --no-fp" + fi + if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO_CLANG}" ]; then + objtoolopt="${objtoolopt} --no-unreachable" + fi + if [ -n "${CONFIG_RETPOLINE}" ]; then + objtoolopt="${objtoolopt} --retpoline" + fi + if [ -n "${CONFIG_X86_SMAP}" ]; then + objtoolopt="${objtoolopt} --uaccess" + fi + if [ -n "${CONFIG_SLS}" ]; then + objtoolopt="${objtoolopt} --sls" + fi + info OBJTOOL ${1} + tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1} fi } # Link of vmlinux -# ${1} - optional extra .o files -# ${2} - output file +# ${1} - output file +# ${2}, ${3}, ... - optional extra .o files vmlinux_link() { local lds="${objtree}/${KBUILD_LDS}" + local output=${1} local objects + local strip_debug + + info LD ${output} + + # skip output file argument + shift + + # The kallsyms linking does not need debug symbols included. + if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then + strip_debug=-Wl,--strip-debug + fi if [ "${SRCARCH}" != "um" ]; then - if [ -z "${CONFIG_LTO_CLANG}" ]; then + if [ -n "${CONFIG_LTO_CLANG}" ]; then + # Use vmlinux.o instead of performing the slow LTO + # link again. objects="--whole-archive \ - built-in.a \ + vmlinux.o \ + --no-whole-archive \ + ${@}" + else + objects="--whole-archive \ + ${KBUILD_VMLINUX_OBJS} \ --no-whole-archive \ --start-group \ ${KBUILD_VMLINUX_LIBS} \ --end-group \ - ${1}" - else - objects="--start-group \ - vmlinux.o \ - --end-group \ - ${1}" + ${@}" fi - ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ + ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \ + ${strip_debug#-Wl,} \ + -o ${output} \ -T ${lds} ${objects} else objects="-Wl,--whole-archive \ - built-in.a \ + ${KBUILD_VMLINUX_OBJS} \ -Wl,--no-whole-archive \ -Wl,--start-group \ ${KBUILD_VMLINUX_LIBS} \ -Wl,--end-group \ - ${1}" + ${@}" - ${CC} ${CFLAGS_vmlinux} -o ${2} \ + ${CC} ${CFLAGS_vmlinux} \ + ${strip_debug} \ + -o ${output} \ -Wl,-T,${lds} \ ${objects} \ -lutil -lrt -lpthread @@ -173,10 +213,44 @@ fi } -# Create ${2} .o file with all symbols from the ${1} object file +# generate .BTF typeinfo from DWARF debuginfo +# ${1} - vmlinux image +# ${2} - file to dump raw BTF data into +gen_btf() +{ + local pahole_ver + + if ! [ -x "$(command -v ${PAHOLE})" ]; then + echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available" + return 1 + fi + + pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') + if [ "${pahole_ver}" -lt "116" ]; then + echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.16" + return 1 + fi + + vmlinux_link ${1} + + info "BTF" ${2} + LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1} + + # Create ${2} which contains just .BTF section but no symbols. Add + # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all + # deletes all symbols including __start_BTF and __stop_BTF, which will + # be redefined in the linker script. Add 2>/dev/null to suppress GNU + # objcopy warnings: "empty loadable segment detected at ..." + ${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \ + --strip-all ${1} ${2} 2>/dev/null + # Change e_type to ET_REL so that it can be used to link final vmlinux. + # Unlike GNU ld, lld does not allow an ET_EXEC input. + printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none +} + +# Create ${2} .S file with all symbols from the ${1} object file kallsyms() { - info KSYM ${2} local kallsymopt; if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then @@ -191,13 +265,34 @@ kallsymopt="${kallsymopt} --base-relative" fi - local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ - ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" + info KSYMS ${2} - local afile="`basename ${2} .o`.S" + if [ -n "${CONFIG_CFI_CLANG}" ]; then + ${PERL} ${srctree}/scripts/generate_cfi_kallsyms.pl ${1} | \ + sort -n > .tmp_kallsyms + else + ${NM} -n ${1} > .tmp_kallsyms + fi - ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile} - ${CC} ${aflags} -c -o ${2} ${afile} + scripts/kallsyms ${kallsymopt} < .tmp_kallsyms > ${2} +} + +# Perform one step in kallsyms generation, including temporary linking of +# vmlinux. +kallsyms_step() +{ + kallsymso_prev=${kallsymso} + kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1} + kallsymso=${kallsyms_vmlinux}.o + kallsyms_S=${kallsyms_vmlinux}.S + + vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} + kallsyms ${kallsyms_vmlinux} ${kallsyms_S} + + info AS ${kallsyms_S} + ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \ + ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ + -c -o ${kallsymso} ${kallsyms_S} } # Create map file with all symbols from ${1} @@ -207,19 +302,20 @@ ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2} } -sortextable() +sorttable() { - ${objtree}/scripts/sortextable ${1} + ${objtree}/scripts/sorttable ${1} } # Delete output files in case of error cleanup() { + rm -f .btf.* rm -f .tmp_System.map - rm -f .tmp_kallsyms* - rm -f .tmp_lto.lds + rm -f .tmp_kallsyms + rm -f .tmp_initcalls.lds + rm -f .tmp_symversions.lds rm -f .tmp_vmlinux* - rm -f built-in.a rm -f System.map rm -f vmlinux rm -f vmlinux.o @@ -239,8 +335,6 @@ } trap on_signals HUP INT QUIT TERM -# -# # Use "make V=1" to debug this script case "${KBUILD_VERBOSE}" in *1*) @@ -267,22 +361,34 @@ fi; # final build of init/ -${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init - -archive_builtin +${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1 #link vmlinux.o modpost_link vmlinux.o +objtool_link vmlinux.o # modpost vmlinux.o to check for section mismatches -${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o +${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1 -if [ -n "${CONFIG_LTO_CLANG}" ]; then - # Call recordmcount if needed - recordmcount vmlinux.o +info MODINFO modules.builtin.modinfo +${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo +info GEN modules.builtin +# The second line aids cases where multiple modules share the same object. +tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' | + tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin + +btf_vmlinux_bin_o="" +if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then + btf_vmlinux_bin_o=.btf.vmlinux.bin.o + if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then + echo >&2 "Failed to generate BTF for vmlinux" + echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF" + exit 1 + fi fi kallsymso="" +kallsymso_prev="" kallsyms_vmlinux="" if [ -n "${CONFIG_KALLSYMS}" ]; then @@ -309,37 +415,32 @@ # a) Verify that the System.map from vmlinux matches the map from # ${kallsymso}. - kallsymso=.tmp_kallsyms2.o - kallsyms_vmlinux=.tmp_vmlinux2 - - # step 1 - vmlinux_link "" .tmp_vmlinux1 - kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o - - # step 2 - vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2 - kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o + kallsyms_step 1 + kallsyms_step 2 # step 3 - size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms1.o) - size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms2.o) + size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev}) + size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso}) if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then - kallsymso=.tmp_kallsyms3.o - kallsyms_vmlinux=.tmp_vmlinux3 - - vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3 - - kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o + kallsyms_step 3 fi fi -info LD vmlinux -vmlinux_link "${kallsymso}" vmlinux +vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} -if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then - info SORTEX vmlinux - sortextable vmlinux +# fill in BTF IDs +if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then + info BTFIDS vmlinux + ${RESOLVE_BTFIDS} vmlinux +fi + +if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then + info SORTTAB vmlinux + if ! sorttable vmlinux; then + echo >&2 Failed to sort kernel tables + exit 1 + fi fi info SYSMAP System.map -- Gitblit v1.6.2