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} - optional extra .o files
  60# ${2} - output file
  61vmlinux_link()
  62{
  63        local lds="${objtree}/${KBUILD_LDS}"
  64        local objects
  65
  66        if [ "${SRCARCH}" != "um" ]; then
  67                objects="--whole-archive                        \
  68                        ${KBUILD_VMLINUX_OBJS}                  \
  69                        --no-whole-archive                      \
  70                        --start-group                           \
  71                        ${KBUILD_VMLINUX_LIBS}                  \
  72                        --end-group                             \
  73                        ${1}"
  74
  75                ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2}      \
  76                        -T ${lds} ${objects}
  77        else
  78                objects="-Wl,--whole-archive                    \
  79                        ${KBUILD_VMLINUX_OBJS}                  \
  80                        -Wl,--no-whole-archive                  \
  81                        -Wl,--start-group                       \
  82                        ${KBUILD_VMLINUX_LIBS}                  \
  83                        -Wl,--end-group                         \
  84                        ${1}"
  85
  86                ${CC} ${CFLAGS_vmlinux} -o ${2}                 \
  87                        -Wl,-T,${lds}                           \
  88                        ${objects}                              \
  89                        -lutil -lrt -lpthread
  90                rm -f linux
  91        fi
  92}
  93
  94# generate .BTF typeinfo from DWARF debuginfo
  95gen_btf()
  96{
  97        local pahole_ver;
  98
  99        if ! [ -x "$(command -v ${PAHOLE})" ]; then
 100                info "BTF" "${1}: pahole (${PAHOLE}) is not available"
 101                return 0
 102        fi
 103
 104        pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
 105        if [ "${pahole_ver}" -lt "113" ]; then
 106                info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13"
 107                return 0
 108        fi
 109
 110        info "BTF" ${1}
 111        LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
 112}
 113
 114# Create ${2} .o file with all symbols from the ${1} object file
 115kallsyms()
 116{
 117        info KSYM ${2}
 118        local kallsymopt;
 119
 120        if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
 121                kallsymopt="${kallsymopt} --all-symbols"
 122        fi
 123
 124        if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then
 125                kallsymopt="${kallsymopt} --absolute-percpu"
 126        fi
 127
 128        if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then
 129                kallsymopt="${kallsymopt} --base-relative"
 130        fi
 131
 132        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
 133                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 134
 135        local afile="`basename ${2} .o`.S"
 136
 137        ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile}
 138        ${CC} ${aflags} -c -o ${2} ${afile}
 139}
 140
 141# Create map file with all symbols from ${1}
 142# See mksymap for additional details
 143mksysmap()
 144{
 145        ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
 146}
 147
 148sortextable()
 149{
 150        ${objtree}/scripts/sortextable ${1}
 151}
 152
 153# Delete output files in case of error
 154cleanup()
 155{
 156        rm -f .tmp_System.map
 157        rm -f .tmp_kallsyms*
 158        rm -f .tmp_vmlinux*
 159        rm -f System.map
 160        rm -f vmlinux
 161        rm -f vmlinux.o
 162}
 163
 164on_exit()
 165{
 166        if [ $? -ne 0 ]; then
 167                cleanup
 168        fi
 169}
 170trap on_exit EXIT
 171
 172on_signals()
 173{
 174        exit 1
 175}
 176trap on_signals HUP INT QUIT TERM
 177
 178#
 179#
 180# Use "make V=1" to debug this script
 181case "${KBUILD_VERBOSE}" in
 182*1*)
 183        set -x
 184        ;;
 185esac
 186
 187if [ "$1" = "clean" ]; then
 188        cleanup
 189        exit 0
 190fi
 191
 192# We need access to CONFIG_ symbols
 193. include/config/auto.conf
 194
 195# Update version
 196info GEN .version
 197if [ -r .version ]; then
 198        VERSION=$(expr 0$(cat .version) + 1)
 199        echo $VERSION > .version
 200else
 201        rm -f .version
 202        echo 1 > .version
 203fi;
 204
 205# final build of init/
 206${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
 207
 208#link vmlinux.o
 209info LD vmlinux.o
 210modpost_link vmlinux.o
 211
 212# modpost vmlinux.o to check for section mismatches
 213${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
 214
 215info MODINFO modules.builtin.modinfo
 216${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
 217
 218kallsymso=""
 219kallsyms_vmlinux=""
 220if [ -n "${CONFIG_KALLSYMS}" ]; then
 221
 222        # kallsyms support
 223        # Generate section listing all symbols and add it into vmlinux
 224        # It's a three step process:
 225        # 1)  Link .tmp_vmlinux1 so it has all symbols and sections,
 226        #     but __kallsyms is empty.
 227        #     Running kallsyms on that gives us .tmp_kallsyms1.o with
 228        #     the right size
 229        # 2)  Link .tmp_vmlinux2 so it now has a __kallsyms section of
 230        #     the right size, but due to the added section, some
 231        #     addresses have shifted.
 232        #     From here, we generate a correct .tmp_kallsyms2.o
 233        # 3)  That link may have expanded the kernel image enough that
 234        #     more linker branch stubs / trampolines had to be added, which
 235        #     introduces new names, which further expands kallsyms. Do another
 236        #     pass if that is the case. In theory it's possible this results
 237        #     in even more stubs, but unlikely.
 238        #     KALLSYMS_EXTRA_PASS=1 may also used to debug or work around
 239        #     other bugs.
 240        # 4)  The correct ${kallsymso} is linked into the final vmlinux.
 241        #
 242        # a)  Verify that the System.map from vmlinux matches the map from
 243        #     ${kallsymso}.
 244
 245        kallsymso=.tmp_kallsyms2.o
 246        kallsyms_vmlinux=.tmp_vmlinux2
 247
 248        # step 1
 249        vmlinux_link "" .tmp_vmlinux1
 250        kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o
 251
 252        # step 2
 253        vmlinux_link .tmp_kallsyms1.o .tmp_vmlinux2
 254        kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o
 255
 256        # step 3
 257        size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms1.o)
 258        size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" .tmp_kallsyms2.o)
 259
 260        if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
 261                kallsymso=.tmp_kallsyms3.o
 262                kallsyms_vmlinux=.tmp_vmlinux3
 263
 264                vmlinux_link .tmp_kallsyms2.o .tmp_vmlinux3
 265
 266                kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o
 267        fi
 268fi
 269
 270info LD vmlinux
 271vmlinux_link "${kallsymso}" vmlinux
 272
 273if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then
 274        gen_btf vmlinux
 275fi
 276
 277if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
 278        info SORTEX vmlinux
 279        sortextable vmlinux
 280fi
 281
 282info SYSMAP System.map
 283mksysmap vmlinux System.map
 284
 285# step a (see comment above)
 286if [ -n "${CONFIG_KALLSYMS}" ]; then
 287        mksysmap ${kallsyms_vmlinux} .tmp_System.map
 288
 289        if ! cmp -s System.map .tmp_System.map; then
 290                echo >&2 Inconsistent kallsyms data
 291                echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
 292                exit 1
 293        fi
 294fi
 295