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        local strip_debug
  67
  68        info LD ${output}
  69
  70        # skip output file argument
  71        shift
  72
  73        # The kallsyms linking does not need debug symbols included.
  74        if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
  75                strip_debug=-Wl,--strip-debug
  76        fi
  77
  78        if [ "${SRCARCH}" != "um" ]; then
  79                objects="--whole-archive                        \
  80                        ${KBUILD_VMLINUX_OBJS}                  \
  81                        --no-whole-archive                      \
  82                        --start-group                           \
  83                        ${KBUILD_VMLINUX_LIBS}                  \
  84                        --end-group                             \
  85                        ${@}"
  86
  87                ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux}      \
  88                        ${strip_debug#-Wl,}                     \
  89                        -o ${output}                            \
  90                        -T ${lds} ${objects}
  91        else
  92                objects="-Wl,--whole-archive                    \
  93                        ${KBUILD_VMLINUX_OBJS}                  \
  94                        -Wl,--no-whole-archive                  \
  95                        -Wl,--start-group                       \
  96                        ${KBUILD_VMLINUX_LIBS}                  \
  97                        -Wl,--end-group                         \
  98                        ${@}"
  99
 100                ${CC} ${CFLAGS_vmlinux}                         \
 101                        ${strip_debug}                          \
 102                        -o ${output}                            \
 103                        -Wl,-T,${lds}                           \
 104                        ${objects}                              \
 105                        -lutil -lrt -lpthread
 106                rm -f linux
 107        fi
 108}
 109
 110# generate .BTF typeinfo from DWARF debuginfo
 111# ${1} - vmlinux image
 112# ${2} - file to dump raw BTF data into
 113gen_btf()
 114{
 115        local pahole_ver
 116
 117        if ! [ -x "$(command -v ${PAHOLE})" ]; then
 118                echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
 119                return 1
 120        fi
 121
 122        pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
 123        if [ "${pahole_ver}" -lt "113" ]; then
 124                echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
 125                return 1
 126        fi
 127
 128        vmlinux_link ${1}
 129
 130        info "BTF" ${2}
 131        LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
 132
 133        # Create ${2} which contains just .BTF section but no symbols. Add
 134        # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all
 135        # deletes all symbols including __start_BTF and __stop_BTF, which will
 136        # be redefined in the linker script. Add 2>/dev/null to suppress GNU
 137        # objcopy warnings: "empty loadable segment detected at ..."
 138        ${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \
 139                --strip-all ${1} ${2} 2>/dev/null
 140        # Change e_type to ET_REL so that it can be used to link final vmlinux.
 141        # Unlike GNU ld, lld does not allow an ET_EXEC input.
 142        printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none
 143}
 144
 145# Create ${2} .o file with all symbols from the ${1} object file
 146kallsyms()
 147{
 148        info KSYM ${2}
 149        local kallsymopt;
 150
 151        if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
 152                kallsymopt="${kallsymopt} --all-symbols"
 153        fi
 154
 155        if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then
 156                kallsymopt="${kallsymopt} --absolute-percpu"
 157        fi
 158
 159        if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then
 160                kallsymopt="${kallsymopt} --base-relative"
 161        fi
 162
 163        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
 164                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 165
 166        local afile="`basename ${2} .o`.S"
 167
 168        ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile}
 169        ${CC} ${aflags} -c -o ${2} ${afile}
 170}
 171
 172# Perform one step in kallsyms generation, including temporary linking of
 173# vmlinux.
 174kallsyms_step()
 175{
 176        kallsymso_prev=${kallsymso}
 177        kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1}
 178        kallsymso=${kallsyms_vmlinux}.o
 179
 180        vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o}
 181        kallsyms ${kallsyms_vmlinux} ${kallsymso}
 182}
 183
 184# Create map file with all symbols from ${1}
 185# See mksymap for additional details
 186mksysmap()
 187{
 188        ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
 189}
 190
 191sorttable()
 192{
 193        ${objtree}/scripts/sorttable ${1}
 194}
 195
 196# Delete output files in case of error
 197cleanup()
 198{
 199        rm -f .btf.*
 200        rm -f .tmp_System.map
 201        rm -f .tmp_vmlinux*
 202        rm -f System.map
 203        rm -f vmlinux
 204        rm -f vmlinux.o
 205}
 206
 207on_exit()
 208{
 209        if [ $? -ne 0 ]; then
 210                cleanup
 211        fi
 212}
 213trap on_exit EXIT
 214
 215on_signals()
 216{
 217        exit 1
 218}
 219trap on_signals HUP INT QUIT TERM
 220
 221#
 222#
 223# Use "make V=1" to debug this script
 224case "${KBUILD_VERBOSE}" in
 225*1*)
 226        set -x
 227        ;;
 228esac
 229
 230if [ "$1" = "clean" ]; then
 231        cleanup
 232        exit 0
 233fi
 234
 235# We need access to CONFIG_ symbols
 236. include/config/auto.conf
 237
 238# Update version
 239info GEN .version
 240if [ -r .version ]; then
 241        VERSION=$(expr 0$(cat .version) + 1)
 242        echo $VERSION > .version
 243else
 244        rm -f .version
 245        echo 1 > .version
 246fi;
 247
 248# final build of init/
 249${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
 250
 251#link vmlinux.o
 252info LD vmlinux.o
 253modpost_link vmlinux.o
 254
 255# modpost vmlinux.o to check for section mismatches
 256${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
 257
 258info MODINFO modules.builtin.modinfo
 259${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
 260info GEN modules.builtin
 261# The second line aids cases where multiple modules share the same object.
 262tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' |
 263        tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin
 264
 265btf_vmlinux_bin_o=""
 266if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
 267        btf_vmlinux_bin_o=.btf.vmlinux.bin.o
 268        if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then
 269                echo >&2 "Failed to generate BTF for vmlinux"
 270                echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF"
 271                exit 1
 272        fi
 273fi
 274
 275kallsymso=""
 276kallsymso_prev=""
 277kallsyms_vmlinux=""
 278if [ -n "${CONFIG_KALLSYMS}" ]; then
 279
 280        # kallsyms support
 281        # Generate section listing all symbols and add it into vmlinux
 282        # It's a three step process:
 283        # 1)  Link .tmp_vmlinux1 so it has all symbols and sections,
 284        #     but __kallsyms is empty.
 285        #     Running kallsyms on that gives us .tmp_kallsyms1.o with
 286        #     the right size
 287        # 2)  Link .tmp_vmlinux2 so it now has a __kallsyms section of
 288        #     the right size, but due to the added section, some
 289        #     addresses have shifted.
 290        #     From here, we generate a correct .tmp_kallsyms2.o
 291        # 3)  That link may have expanded the kernel image enough that
 292        #     more linker branch stubs / trampolines had to be added, which
 293        #     introduces new names, which further expands kallsyms. Do another
 294        #     pass if that is the case. In theory it's possible this results
 295        #     in even more stubs, but unlikely.
 296        #     KALLSYMS_EXTRA_PASS=1 may also used to debug or work around
 297        #     other bugs.
 298        # 4)  The correct ${kallsymso} is linked into the final vmlinux.
 299        #
 300        # a)  Verify that the System.map from vmlinux matches the map from
 301        #     ${kallsymso}.
 302
 303        kallsyms_step 1
 304        kallsyms_step 2
 305
 306        # step 3
 307        size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev})
 308        size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
 309
 310        if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
 311                kallsyms_step 3
 312        fi
 313fi
 314
 315vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o}
 316
 317if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then
 318        info SORTTAB vmlinux
 319        if ! sorttable vmlinux; then
 320                echo >&2 Failed to sort kernel tables
 321                exit 1
 322        fi
 323fi
 324
 325info SYSMAP System.map
 326mksysmap vmlinux System.map
 327
 328# step a (see comment above)
 329if [ -n "${CONFIG_KALLSYMS}" ]; then
 330        mksysmap ${kallsyms_vmlinux} .tmp_System.map
 331
 332        if ! cmp -s System.map .tmp_System.map; then
 333                echo >&2 Inconsistent kallsyms data
 334                echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
 335                exit 1
 336        fi
 337fi
 338