linux/scripts/link-vmlinux.sh
<<
>>
Prefs
   1#!/bin/sh
   2# SPDX-License-Identifier: GPL-2.0
   3#
   4# link vmlinux
   5#
   6# vmlinux is linked from the objects selected by $(KBUILD_VMLINUX_OBJS) and
   7# $(KBUILD_VMLINUX_LIBS). Most are built-in.a files from top-level directories
   8# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
   9# $(KBUILD_VMLINUX_LIBS) are archives which are linked conditionally
  10# (not within --whole-archive), and do not require symbol indexes added.
  11#
  12# vmlinux
  13#   ^
  14#   |
  15#   +--< $(KBUILD_VMLINUX_OBJS)
  16#   |    +--< init/built-in.a drivers/built-in.a mm/built-in.a + more
  17#   |
  18#   +--< $(KBUILD_VMLINUX_LIBS)
  19#   |    +--< lib/lib.a + more
  20#   |
  21#   +-< ${kallsymso} (see description in KALLSYMS section)
  22#
  23# vmlinux version (uname -v) cannot be updated during normal
  24# descending-into-subdirs phase since we do not yet know if we need to
  25# update vmlinux.
  26# Therefore this step is delayed until just before final link of vmlinux.
  27#
  28# System.map is generated to document addresses of all kernel symbols
  29
  30# Error out on error
  31set -e
  32
  33# Nice output in kbuild format
  34# Will be supressed by "make -s"
  35info()
  36{
  37        if [ "${quiet}" != "silent_" ]; then
  38                printf "  %-7s %s\n" "${1}" "${2}"
  39        fi
  40}
  41
  42# Link of vmlinux.o used for section mismatch analysis
  43# ${1} output file
  44modpost_link()
  45{
  46        local objects
  47
  48        objects="--whole-archive                                \
  49                ${KBUILD_VMLINUX_OBJS}                          \
  50                --no-whole-archive                              \
  51                --start-group                                   \
  52                ${KBUILD_VMLINUX_LIBS}                          \
  53                --end-group"
  54
  55        ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
  56}
  57
  58# Link of vmlinux
  59# ${1} - output file
  60# ${2}, ${3}, ... - optional extra .o files
  61vmlinux_link()
  62{
  63        local lds="${objtree}/${KBUILD_LDS}"
  64        local output=${1}
  65        local objects
  66
  67        info LD ${output}
  68
  69        # skip output file argument
  70        shift
  71
  72        if [ "${SRCARCH}" != "um" ]; then
  73                objects="--whole-archive                        \
  74                        ${KBUILD_VMLINUX_OBJS}                  \
  75                        --no-whole-archive                      \
  76                        --start-group                           \
  77                        ${KBUILD_VMLINUX_LIBS}                  \
  78                        --end-group                             \
  79                        ${@}"
  80
  81                ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux}      \
  82                        -o ${output}                            \
  83                        -T ${lds} ${objects}
  84        else
  85                objects="-Wl,--whole-archive                    \
  86                        ${KBUILD_VMLINUX_OBJS}                  \
  87                        -Wl,--no-whole-archive                  \
  88                        -Wl,--start-group                       \
  89                        ${KBUILD_VMLINUX_LIBS}                  \
  90                        -Wl,--end-group                         \
  91                        ${@}"
  92
  93                ${CC} ${CFLAGS_vmlinux}                         \
  94                        -o ${output}                            \
  95                        -Wl,-T,${lds}                           \
  96                        ${objects}                              \
  97                        -lutil -lrt -lpthread
  98                rm -f linux
  99        fi
 100}
 101
 102# generate .BTF typeinfo from DWARF debuginfo
 103# ${1} - vmlinux image
 104# ${2} - file to dump raw BTF data into
 105gen_btf()
 106{
 107        local pahole_ver
 108        local bin_arch
 109
 110        if ! [ -x "$(command -v ${PAHOLE})" ]; then
 111                echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
 112                return 1
 113        fi
 114
 115        pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
 116        if [ "${pahole_ver}" -lt "113" ]; then
 117                echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
 118                return 1
 119        fi
 120
 121        info "BTF" ${2}
 122        vmlinux_link ${1}
 123        LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
 124
 125        # dump .BTF section into raw binary file to link with final vmlinux
 126        bin_arch=$(LANG=C ${OBJDUMP} -f ${1} | grep architecture | \
 127                cut -d, -f1 | cut -d' ' -f2)
 128        bin_format=$(LANG=C ${OBJDUMP} -f ${1} | grep 'file format' | \
 129                awk '{print $4}')
 130        ${OBJCOPY} --change-section-address .BTF=0 \
 131                --set-section-flags .BTF=alloc -O binary \
 132                --only-section=.BTF ${1} .btf.vmlinux.bin
 133        ${OBJCOPY} -I binary -O ${bin_format} -B ${bin_arch} \
 134                --rename-section .data=.BTF .btf.vmlinux.bin ${2}
 135}
 136
 137# Create ${2} .o file with all symbols from the ${1} object file
 138kallsyms()
 139{
 140        info KSYM ${2}
 141        local kallsymopt;
 142
 143        if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
 144                kallsymopt="${kallsymopt} --all-symbols"
 145        fi
 146
 147        if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then
 148                kallsymopt="${kallsymopt} --absolute-percpu"
 149        fi
 150
 151        if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then
 152                kallsymopt="${kallsymopt} --base-relative"
 153        fi
 154
 155        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
 156                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 157
 158        local afile="`basename ${2} .o`.S"
 159
 160        ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile}
 161        ${CC} ${aflags} -c -o ${2} ${afile}
 162}
 163
 164# Perform one step in kallsyms generation, including temporary linking of
 165# vmlinux.
 166kallsyms_step()
 167{
 168        kallsymso_prev=${kallsymso}
 169        kallsymso=.tmp_kallsyms${1}.o
 170        kallsyms_vmlinux=.tmp_vmlinux${1}
 171
 172        vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
 173        kallsyms ${kallsyms_vmlinux} ${kallsymso}
 174}
 175
 176# Create map file with all symbols from ${1}
 177# See mksymap for additional details
 178mksysmap()
 179{
 180        ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
 181}
 182
 183sorttable()
 184{
 185        ${objtree}/scripts/sorttable ${1}
 186}
 187
 188# Delete output files in case of error
 189cleanup()
 190{
 191        rm -f .btf.*
 192        rm -f .tmp_System.map
 193        rm -f .tmp_kallsyms*
 194        rm -f .tmp_vmlinux*
 195        rm -f System.map
 196        rm -f vmlinux
 197        rm -f vmlinux.o
 198}
 199
 200on_exit()
 201{
 202        if [ $? -ne 0 ]; then
 203                cleanup
 204        fi
 205}
 206trap on_exit EXIT
 207
 208on_signals()
 209{
 210        exit 1
 211}
 212trap on_signals HUP INT QUIT TERM
 213
 214#
 215#
 216# Use "make V=1" to debug this script
 217case "${KBUILD_VERBOSE}" in
 218*1*)
 219        set -x
 220        ;;
 221esac
 222
 223if [ "$1" = "clean" ]; then
 224        cleanup
 225        exit 0
 226fi
 227
 228# We need access to CONFIG_ symbols
 229. include/config/auto.conf
 230
 231# Update version
 232info GEN .version
 233if [ -r .version ]; then
 234        VERSION=$(expr 0$(cat .version) + 1)
 235        echo $VERSION > .version
 236else
 237        rm -f .version
 238        echo 1 > .version
 239fi;
 240
 241# final build of init/
 242${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
 243
 244#link vmlinux.o
 245info LD vmlinux.o
 246modpost_link vmlinux.o
 247
 248# modpost vmlinux.o to check for section mismatches
 249${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
 250
 251info MODINFO modules.builtin.modinfo
 252${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
 253info GEN modules.builtin
 254# The second line aids cases where multiple modules share the same object.
 255tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' |
 256        tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin
 257
 258btf_vmlinux_bin_o=""
 259if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
 260        if gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then
 261                btf_vmlinux_bin_o=.btf.vmlinux.bin.o
 262        else
 263                echo >&2 "Failed to generate BTF for vmlinux"
 264                echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF"
 265                exit 1
 266        fi
 267fi
 268
 269kallsymso=""
 270kallsymso_prev=""
 271kallsyms_vmlinux=""
 272if [ -n "${CONFIG_KALLSYMS}" ]; then
 273
 274        # kallsyms support
 275        # Generate section listing all symbols and add it into vmlinux
 276        # It's a three step process:
 277        # 1)  Link .tmp_vmlinux1 so it has all symbols and sections,
 278        #     but __kallsyms is empty.
 279        #     Running kallsyms on that gives us .tmp_kallsyms1.o with
 280        #     the right size
 281        # 2)  Link .tmp_vmlinux2 so it now has a __kallsyms section of
 282        #     the right size, but due to the added section, some
 283        #     addresses have shifted.
 284        #     From here, we generate a correct .tmp_kallsyms2.o
 285        # 3)  That link may have expanded the kernel image enough that
 286        #     more linker branch stubs / trampolines had to be added, which
 287        #     introduces new names, which further expands kallsyms. Do another
 288        #     pass if that is the case. In theory it's possible this results
 289        #     in even more stubs, but unlikely.
 290        #     KALLSYMS_EXTRA_PASS=1 may also used to debug or work around
 291        #     other bugs.
 292        # 4)  The correct ${kallsymso} is linked into the final vmlinux.
 293        #
 294        # a)  Verify that the System.map from vmlinux matches the map from
 295        #     ${kallsymso}.
 296
 297        kallsyms_step 1
 298        kallsyms_step 2
 299
 300        # step 3
 301        size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev})
 302        size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
 303
 304        if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
 305                kallsyms_step 3
 306        fi
 307fi
 308
 309vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
 310
 311if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
 312        info SORTTAB vmlinux
 313        if ! sorttable vmlinux; then
 314                echo >&2 Failed to sort kernel tables
 315                exit 1
 316        fi
 317fi
 318
 319info SYSMAP System.map
 320mksysmap vmlinux System.map
 321
 322# step a (see comment above)
 323if [ -n "${CONFIG_KALLSYMS}" ]; then
 324        mksysmap ${kallsyms_vmlinux} .tmp_System.map
 325
 326        if ! cmp -s System.map .tmp_System.map; then
 327                echo >&2 Inconsistent kallsyms data
 328                echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
 329                exit 1
 330        fi
 331fi
 332