1# SPDX-License-Identifier: GPL-2.0 2# 3# Helpers for the objtool klp tests. A test builds a fixture twice, as the 4# original and (with -DPATCHED) the patched object, runs both through 5# "klp checksum" and diffs them, then asserts on the result. 6# 7# Assertions check properties rather than compare against recorded output: 8# codegen varies between compilers and golden files would report churn instead 9# of regressions. 10 11TESTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 12 13# Tests live in generic/ or in an architecture directory beside it, and each 14# carries its own fixtures. 15FIXTURES_DIR="$(cd "$(dirname "$0")/fixtures" 2>/dev/null && pwd)" 16 17# The kernel's convention: CROSS_COMPILE is the one knob, with per-tool 18# overrides for what it does not cover. objtool itself is always a host binary 19# -- it is built with HOSTCC and only reads ELF -- so an arm64 machine can run 20# the x86 tests against x86 objects given a compiler that emits them. 21# 22# readelf reads any target, so it rarely needs overriding, and either GNU 23# readelf or llvm-readelf will do: the assertions match on fields rather than 24# on columns, and where the two spell something differently -- "OS [0xff20]" 25# against "OS[0xff20]" for SHN_LIVEPATCH -- they accept both. BFD's objcopy is 26# usually built for the host's target alone, and llvm-objcopy is the 27# target-agnostic replacement. 28CROSS_COMPILE="${CROSS_COMPILE:-}" 29CC="${CC:-${CROSS_COMPILE}gcc}" 30LD="${LD:-${CROSS_COMPILE}ld}" 31READELF="${READELF:-${CROSS_COMPILE}readelf}" 32OBJCOPY="${OBJCOPY:-${CROSS_COMPILE}objcopy}" 33 34OBJTOOL="${OBJTOOL:-$TESTS_DIR/../objtool}" 35 36# klp_preflight 37# 38# Check the environment once, before any test runs, and report what was found. 39# 40klp_preflight() 41{ 42 local tmp tool cc_version arch host cc_arch 43 44 bail() { echo "Bail out! $*" >&2; exit 1; } 45 46 # A relative $OBJTOOL is relative to the objtool directory, not tests/. 47 [ -x "$OBJTOOL" ] || [ ! -x "$TESTS_DIR/../$OBJTOOL" ] || 48 OBJTOOL="$TESTS_DIR/../$OBJTOOL" 49 50 [ -x "$OBJTOOL" ] || 51 bail "objtool not found at '$OBJTOOL' -- build it first" 52 53 # run_diff() runs objtool from inside the test's working directory, so 54 # a relative path would resolve against that instead. 55 OBJTOOL="$(realpath "$OBJTOOL")" 56 57 "$OBJTOOL" klp 2>&1 | grep -q checksum || 58 bail "objtool was built without klp support; install libxxhash (>= 0.8) and rebuild" 59 60 command -v "${CC%% *}" >/dev/null || bail "compiler not found: $CC" 61 62 for tool in "$READELF" "$OBJCOPY" "$LD"; do 63 command -v "${tool%% *}" >/dev/null || bail "$tool not found" 64 done 65 66 tmp="$(mktemp -d)" || bail "mktemp failed" 67 echo 'int probe(void) { return 0; }' > "$tmp/probe.c" 68 $CC -c -o "$tmp/probe.o" "$tmp/probe.c" 2>/dev/null || 69 { rm -rf "$tmp"; bail "$CC cannot compile a trivial object"; } 70 71 # $CC, $ARCH and objtool have to agree about the target, and cross runs 72 # are where they stop agreeing: plain "CC=clang ARCH=x86_64" on an arm64 73 # box selects the x86 tests and then builds arm64 objects, because clang 74 # needs --target= to emit anything but the host's. 75 # 76 # Ask objtool rather than comparing machine names. It rejects an object 77 # it was not built for -- "unexpected ELF machine type" -- so one check 78 # covers every way the three can disagree, and says so once instead of 79 # failing every test for the same reason. 80 "$OBJTOOL" klp checksum "$tmp/probe.o" >/dev/null 2>&1 || 81 { rm -rf "$tmp" 82 bail "objtool rejects an object built by '$CC'; they target" \ 83 "different architectures (set CROSS_COMPILE, or" \ 84 "--target= for clang)"; } 85 86 # BFD objcopy is usually built for the host's target alone, and 87 # checksum_of() needs it to read the object under test. 88 $OBJCOPY -O binary --only-section=.text "$tmp/probe.o" "$tmp/probe.bin" 2>/dev/null || 89 { rm -rf "$tmp" 90 bail "$OBJCOPY cannot read objects built by '$CC'; install" \ 91 "binutils-multiarch or set OBJCOPY=llvm-objcopy"; } 92 # $ARCH only chooses which directory of tests runs, so it can disagree 93 # with what $CC builds without objtool noticing -- and the result is the 94 # wrong set of tests, quietly. 95 case "$($READELF -hW "$tmp/probe.o" | sed -n 's/.*Machine: *//p')" in 96 *X86-64*|*Intel*80386*) cc_arch=x86 ;; 97 *AArch64*) cc_arch=arm64 ;; 98 *) cc_arch= ;; 99 esac 100 rm -rf "$tmp" 101 102 # Normalize to the kernel's SRCARCH. 103 case "${ARCH:-$(uname -m)}" in 104 x86_64|i?86) arch=x86 ;; 105 aarch64*) arch=arm64 ;; 106 *) arch="${ARCH:-$(uname -m)}" ;; 107 esac 108 109 case "$(uname -m)" in 110 x86_64|i?86) host=x86 ;; 111 aarch64*) host=arm64 ;; 112 *) host="$(uname -m)" ;; 113 esac 114 115 [ -z "$cc_arch" ] || [ "$cc_arch" = "$arch" ] || 116 bail "ARCH says $arch but '$CC' builds $cc_arch objects;" \ 117 "the $arch tests would run against the wrong architecture" 118 119 KLP_TEST_ARCH="$arch" 120 KLP_TEST_PREFLIGHT=done 121 export OBJTOOL CC KLP_TEST_ARCH KLP_TEST_PREFLIGHT 122 123 cc_version="$($CC --version 2>/dev/null | head -1)" 124 cat <<EOF 125# preflight 126# objtool $OBJTOOL (klp: yes) 127# compiler $cc_version 128# arch $KLP_TEST_ARCH$([ "$arch" = "$host" ] || echo " (host $host, cross)") 129# tmpdir ${TMPDIR:-/tmp} (each test builds in a fresh directory here) 130EOF 131} 132 133[ -n "${KLP_TEST_PREFLIGHT:-}" ] || klp_preflight 134 135# What every fixture is built with. These describe the kernel a fixture stands 136# in for; -c is build_one's contract rather than a property of that kernel, so 137# it lives at the compile where an override cannot drop it. 138# 139# -O2 the kernel's default 140# -ffunction-sections -fdata-sections klp-build passes these itself, through 141# KCFLAGS, whatever the configuration 142# -fno-asynchronous-unwind-tables arch/x86/Makefile sets this always, so 143# kernel objects carry no .eh_frame 144# -fno-common the kernel's Makefile sets it, so an 145# uninitialised global there lands in 146# .bss rather than being SHN_COMMON, 147# which has no section and so no 148# checksum 149# 150# A test overrides it; see tools/objtool/Documentation/klp-write-tests.txt. 151FIXTURE_CFLAGS="-O2 -ffunction-sections -fdata-sections -fno-common \ 152 -fno-asynchronous-unwind-tables" 153 154test_name="$(basename "$0" .sh)" 155workdir= 156 157# The pair run_diff() and the checksum helpers work on. build_pair() names 158# them again and make_vmlinux_pair() repoints orig_obj at the image it links, 159# but a test which builds its objects itself with build_one() sets neither, so 160# the default belongs here. 161orig_obj=orig.o 162patched_obj=patched.o 163 164pass() { echo "ok - $test_name${1:+: $1}"; exit 0; } 165fail() { echo "not ok - $test_name: $1"; exit 1; } 166 167# Two kinds of skip, and the runner tells them apart. 168# 169# declared_skip the test said in advance it does not apply here, e.g. 170# gcc_only on a clang run. Expected indefinitely. 171# probe_skip the construct did not turn up in the built object this 172# time. Weaker: it may appear on another compiler version, 173# and one which becomes permanent is a fixture that quietly 174# stopped testing anything. 175# 176# A bare skip() is neither, and the runner counts it as a failure: a test which 177# gives up for a reason it never declared is a hole, not an outcome. 178declared_skip() { echo "ok - $test_name # SKIP (declared) $*"; exit 0; } 179probe_skip() { echo "ok - $test_name # SKIP (probe) $*"; exit 0; } 180skip() { echo "ok - $test_name # SKIP $*"; exit 0; } 181 182# TAP directives. A test which is known to fail reports it rather than being 183# commented out and forgotten, and one which starts passing again says so 184# instead of quietly going green: the expectation has to be removed by hand, 185# which is the point. 186xfail() 187{ 188 echo "not ok - $test_name${1:+: $1} # TODO known failure" 189 exit 0 190} 191 192xpass() 193{ 194 echo "ok - $test_name${1:+: $1} # TODO expected failure, but passed" 195 exit 1 196} 197 198cleanup() 199{ 200 [ -n "$workdir" ] || return 0 201 202 if [ -n "${KLP_TEST_KEEP:-}" ]; then 203 [ -n "${KLP_TEST_WORKDIR:-}" ] || echo "# kept $workdir" 204 return 0 205 fi 206 207 rm -rf "$workdir" 208} 209 210# setup [exported symbol...] 211setup() 212{ 213 if [ -n "${KLP_TEST_WORKDIR:-}" ]; then 214 workdir="$KLP_TEST_WORKDIR" 215 mkdir -p "$workdir" || fail "cannot create $workdir" 216 else 217 workdir="$(mktemp -d)" || fail "mktemp failed" 218 fi 219 trap cleanup EXIT 220 221 export_syms "$@" 222} 223 224# export_syms [symbol...] 225# 226# Rewrite Module.symvers so exactly these symbols are exported by vmlinux. 227# Whether a symbol is listed decides between an ordinary relocation and a klp 228# relocation, so tests flip it to cover both. 229export_syms() 230{ 231 : > "$workdir/Module.symvers" 232 add_exports vmlinux "$@" 233} 234 235# add_exports <object> [symbol...] 236# 237# Append exports owned by one object, without clearing what is already there, 238# so a test can describe a kernel where several objects export things. 239# 240# Which object owns a symbol is not cosmetic: a reference to a vmlinux symbol 241# is applied when the patch module loads, and a reference to a module's symbol 242# when that patched module loads, so klp diff files them in different sections. 243add_exports() 244{ 245 local owner="$1"; shift 246 247 add_exports_ns "$owner" "" "$@" 248} 249 250# add_exports_ns <object> <namespace> [symbol...] 251# 252# Exports in a symbol namespace, the last field of a Module.symvers line. 253# 254# A "module:<names>" namespace is EXPORT_SYMBOL_FOR_MODULES(), where the module 255# loader grants access by matching the importing module's name against the 256# list. A livepatch module is never on that list, so such a symbol has to be 257# referenced the way an unexported one is. Ordinary namespaces are not 258# special here. 259add_exports_ns() 260{ 261 local owner="$1" ns="$2"; shift 2 262 263 local sym 264 265 for sym in "$@"; do 266 printf '0x00000000\t%s\t%s\tEXPORT_SYMBOL\t%s\n' \ 267 "$sym" "$owner" "$ns" >> "$workdir/Module.symvers" 268 done 269} 270 271# gcc_only / clang_only <reason> 272gcc_only() 273{ 274 case "$($CC --version 2>/dev/null | head -1)" in 275 *[Gg][Cc][Cc]*) return 0 ;; 276 esac 277 declared_skip "gcc only${1:+: $1}" 278} 279 280clang_only() 281{ 282 case "$($CC --version 2>/dev/null | head -1)" in 283 *clang*) return 0 ;; 284 esac 285 declared_skip "clang only${1:+: $1}" 286} 287 288# build_one <fixture.c> <output object> [cflags...] 289build_one() 290{ 291 local fixture out 292 fixture="$FIXTURES_DIR/$1" 293 out="$workdir/$2" 294 shift 2 295 296 [ -f "$fixture" ] || fail "missing fixture $fixture" 297 298 # run_checksum only runs once per workdir. A fresh object has no 299 # checksums in it, so anything built now needs that to happen again. 300 rm -f "$workdir/.checksummed" 301 302 $CC -c $FIXTURE_CFLAGS "$@" -o "$out" "$fixture" 2>"$workdir/cc.log" || 303 fail "$(basename "$fixture") does not build: $(tail -1 "$workdir/cc.log")" 304} 305 306# build_pair <fixture.c> [cflags...] 307build_pair() 308{ 309 local fixture="$1"; shift 310 311 # Name what this builds. A test may run several segments, and 312 # make_vmlinux_pair() repoints orig_obj at the image it links, so 313 # without this the next run_diff() would still be reading that. 314 orig_obj=orig.o 315 patched_obj=patched.o 316 317 build_one "$fixture" orig.o "$@" 318 build_one "$fixture" patched.o "$@" -DPATCHED 319} 320 321# run_objtool_check <objtool arguments...> 322# 323# Run objtool's ordinary check pass over the pair, as the kernel build does. 324# 325# Some of what klp diff consumes is produced by this pass rather than by the 326# compiler: .static_call_sites, .mcount_loc, .ibt_endbr_seal, ORC. 327# 328# Only module objects see it before klp-build -- with CONFIG_KLP_BUILD the 329# per-object pass is deferred, so built-in objects reach klp diff exactly as 330# the compiler left them. 331run_objtool_check() 332{ 333 local obj 334 335 # This rewrites both objects, so checksums taken before it describe 336 # something that no longer exists. As in build_one(), drop the marker 337 # so run_checksum() takes them again. 338 rm -f "$workdir/.checksummed" 339 340 for obj in "$orig_obj" "$patched_obj"; do 341 "$OBJTOOL" "$@" "$workdir/$obj" || 342 fail "objtool $* failed on $obj" 343 done 344} 345 346run_checksum() 347{ 348 # Checksums live in the objects, and a test may ask for them more than 349 # once -- diffing the same pair again with a different Module.symvers, 350 # say. objtool does the right thing when asked twice, leaving the 351 # object alone, but it says so, and that warning would be most of what 352 # a passing run prints. Remember instead, and keep quiet. 353 [ -e "$workdir/.checksummed" ] && return 0 354 355 "$OBJTOOL" klp checksum "$workdir/$orig_obj" || 356 fail "klp checksum $orig_obj failed" 357 "$OBJTOOL" klp checksum "$workdir/$patched_obj" || 358 fail "klp checksum $patched_obj failed" 359 touch "$workdir/.checksummed" 360} 361 362# run_diff [expected exit status] 363run_diff() 364{ 365 local expect="${1:-0}" rc=0 366 367 run_checksum 368 369 # klp diff looks for Module.symvers relative to the working directory. 370 ( cd "$workdir" && "$OBJTOOL" klp diff "$orig_obj" "$patched_obj" out.o ) \ 371 > "$workdir/diff.log" 2>&1 || rc=$? 372 373 [ "$rc" = "$expect" ] || 374 fail "klp diff exited $rc, expected $expect: $(tail -2 "$workdir/diff.log")" 375} 376 377cc_supports() 378{ 379 echo 'int f(void) { return 0; }' > "$workdir/flagtest.c" 380 $CC $1 -c "$workdir/flagtest.c" -o "$workdir/flagtest.o" 2>/dev/null 381} 382 383# partial_link <output> <object...> 384# 385# "ld -r" through the compiler driver so the link targets the same 386# architecture as the objects. 387partial_link() 388{ 389 local out="$1"; shift 390 391 rm -f "$workdir/.checksummed" 392 393 $CC -r -nostdlib -o "$out" "$@" 2>/dev/null || 394 $CC -r -nostdlib -fuse-ld=lld -o "$out" "$@" 2>/dev/null 395} 396 397# link_vmlinux <output> <object...> 398# 399# Link objects into an executable, the way the kernel's final link produces 400# vmlinux from vmlinux.o. Entry point 0 and no libc: nothing runs it, it only 401# has to be a linked image with resolved addresses. 402# 403# The sub-sections have to come out in name order rather than object order, 404# the way the kernel's linker script gathers .text.unlikely and .data.. apart 405# from the rest. That reordering is the entire reason .klp.symid exists: a 406# link which preserves order cannot tell a correct sympos from one that merely 407# counted, and the caller checks the two orders really did diverge. 408# 409# A linker script rather than --sort-section=name, because lld accepts that 410# option and ignores it -- so on a host where only lld can link the target, the 411# test would quietly stop testing the thing it is named for. 412# 413# Three attempts because a cross run has neither $LD nor the compiler's default 414# linker able to touch the target: on an arm64 host linking x86 objects, only 415# lld will do it. 416link_vmlinux() 417{ 418 local out="$1" lds="$workdir/sort.lds"; shift 419 420 echo 'SECTIONS { .data : { *(SORT_BY_NAME(.data.*)) } }' > "$lds" 421 422 $LD -e 0 -T "$lds" -o "$out" "$@" 2>/dev/null || 423 $CC -nostdlib -Wl,-e,0 -Wl,-T,"$lds" \ 424 -o "$out" "$@" 2>/dev/null || 425 $CC -nostdlib -fuse-ld=lld -Wl,-e,0 -Wl,-T,"$lds" \ 426 -o "$out" "$@" 2>/dev/null 427} 428 429# make_vmlinux_pair <orig object...> -- <patched object...> 430# 431# Build the vmlinux.o / vmlinux pair klp diff needs to resolve sympos the way 432# it does for built-in code, and point the diff at it. 433# 434# For a module, sympos is a count in symbol table order, which klp diff can do 435# from the object alone. vmlinux is different: the final link reorders 436# sub-sections, so the position comes from the linked image, bridged by 437# .klp.symid. klp diff only looks for that when the object it was handed is 438# called vmlinux.o and a vmlinux sits beside it -- so both the name and the 439# linked image matter. 440make_vmlinux_pair() 441{ 442 local orig=() patched=() seen= arg 443 444 for arg in "$@"; do 445 if [ "$arg" = -- ]; then seen=y; continue; fi 446 if [ -n "$seen" ]; then patched+=( "$arg" ); else orig+=( "$arg" ); fi 447 done 448 449 # Both sides have to have been named. Without this, forgetting the -- 450 # leaves one list empty, the link of nothing fails, and the test skips 451 # saying the toolchain cannot link -- which is a test bug wearing the 452 # costume of an environment one. 453 [ "${#orig[@]}" -gt 0 ] && [ "${#patched[@]}" -gt 0 ] || 454 fail "make_vmlinux_pair needs objects either side of --" 455 456 partial_link "$workdir/vmlinux.o" "${orig[@]}" || 457 probe_skip "partial link unavailable" 458 partial_link "$workdir/patched.o" "${patched[@]}" || 459 probe_skip "partial link unavailable" 460 461 "$OBJTOOL" --klp-symids --link "$workdir/vmlinux.o" || 462 fail "objtool --klp-symids failed" 463 464 link_vmlinux "$workdir/vmlinux" "$workdir/vmlinux.o" || 465 probe_skip "cannot link a vmlinux here" 466 467 orig_obj=vmlinux.o 468} 469 470# build_module_pair <fixture.c> <module name> [cflags...] 471# 472# Build the pair as objects belonging to a module rather than to vmlinux. klp 473# diff reads the object's module name from .modinfo, and that decides which 474# object a relocation is attributed to and whether a reference counts as 475# cross-module, so a good deal of the code has a module path the vmlinux 476# fixtures never reach. 477# 478# The fixture defines its .modinfo name from MODNAME. Passing that through 479# -D needs two levels of quoting, which is easy to get wrong at the call site. 480build_module_pair() 481{ 482 local fixture="$1" modname="$2"; shift 2 483 484 build_pair "$fixture" -DMODNAME="\"$modname\"" "$@" 485} 486 487# find_thinlto_toolchain 488# 489# Set $THIN_LD to an lld from the same LLVM release as $CC (or THIN_CC). A 490# mismatched pair fails with "Invalid summary version", which reads like a 491# broken test rather than a broken environment. 492# 493# ThinLTO is clang-only; callers must use clang_only before calling this. 494# Only $CC (or an explicit THIN_CC override) is consulted -- the harness does 495# not search for a second compiler beside a gcc $CC. 496find_thinlto_toolchain() 497{ 498 local cc ver ld 499 500 for cc in "${THIN_CC:-}" "$CC"; do 501 [ -n "$cc" ] || continue 502 command -v "${cc%% *}" >/dev/null 2>&1 || return 1 503 504 ver=$($cc -dumpversion 2>/dev/null | cut -d. -f1) 505 506 for ld in "${THIN_LD:-}" "ld.lld-$ver" ld.lld; do 507 [ -n "$ld" ] || continue 508 command -v "$ld" >/dev/null 2>&1 || continue 509 510 echo 'int probe(void) { return 0; }' > "$workdir/probe.c" 511 $cc -flto=thin -O2 -c "$workdir/probe.c" \ 512 -o "$workdir/probe.o" 2>/dev/null || continue 513 "$ld" -r "$workdir/probe.o" -o "$workdir/probe.elf" \ 514 2>/dev/null || continue 515 516 THIN_CC="$cc" 517 THIN_LD="$ld" 518 return 0 519 done 520 done 521 522 return 1 523} 524 525out_sections() { $READELF -S -W "$workdir/out.o" 2>/dev/null; } 526out_relocs() { $READELF -r -W "$workdir/out.o" 2>/dev/null; } 527out_symbols() { $READELF -s -W "$workdir/out.o" 2>/dev/null; } 528diff_log() { cat "$workdir/diff.log"; } 529 530# out_strings <section> 531# 532# The strings in one section of the output, for the names livepatch matches on. 533out_strings() { $READELF -p "$1" "$workdir/out.o" 2>/dev/null; } 534 535# Checks on the input objects, to run before klp diff. The two forms differ in 536# what an absent construct means: 537# 538# require_* the compiler cannot produce it here -> skip 539# assert_* the fixture is supposed to produce it -> fail 540 541in_sections() { $READELF -S -W "$workdir/$1" 2>/dev/null; } 542in_symbols() { $READELF -s -W "$workdir/$1" 2>/dev/null; } 543in_relocs() { $READELF -r -W "$workdir/$1" 2>/dev/null; } 544 545# count_input_symbols <object> <name> 546# 547# How many object symbols of exactly that name the input has. Deliberately not 548# a grep: readelf lists section symbols too, and a newer binutils prints their 549# name -- ".data.<name>" -- where an older one leaves the column blank. A dot 550# is not a word character, so "grep -w <name>" counts that line as well, and 551# the same object gives a different answer depending on which readelf reads it. 552count_input_symbols() 553{ 554 in_symbols "$1" | awk -v n="$2" '$4 == "OBJECT" && $8 == n' | wc -l 555} 556 557# re_quote <string> 558# 559# A string as a literal basic regular expression. Nearly every name these 560# assertions match on contains a dot -- .text.target, .klp.rela.vmlinux -- and 561# an unescaped dot matches any character, so an assertion for one section can be 562# satisfied by a different one whose name merely lines up. 563re_quote() { printf '%s' "$1" | sed 's|[].[^$*\\/]|\\&|g'; } 564 565has_input_section() { in_sections "$1" | grep -q "[[:space:]]$(re_quote "$2")[[:space:]]"; } 566has_input_symbol() { in_symbols "$1" | awk -v n="$2" '$NF == n' | grep -q .; } 567 568assert_input_section() 569{ 570 local obj 571 572 for obj in "$orig_obj" "$patched_obj"; do 573 has_input_section "$obj" "$1" || 574 fail "fixture produced no section '$1' in $obj" 575 done 576} 577 578assert_input_symbol() 579{ 580 local obj 581 582 for obj in "$orig_obj" "$patched_obj"; do 583 has_input_symbol "$obj" "$1" || 584 fail "fixture produced no symbol '$1' in $obj" 585 done 586} 587 588require_input_section() 589{ 590 local obj 591 592 for obj in "$orig_obj" "$patched_obj"; do 593 has_input_section "$obj" "$1" || 594 probe_skip "compiler produced no section '$1' here" 595 done 596} 597 598assert_section() 599{ 600 out_sections | grep -q "[[:space:]]$(re_quote "$1")[[:space:]]" || 601 fail "expected section '$1' in output" 602} 603 604assert_no_section() 605{ 606 out_sections | grep -q "[[:space:]]$(re_quote "$1")[[:space:]]" && 607 fail "unexpected section '$1' in output" 608 return 0 609} 610 611assert_patched() 612{ 613 assert_section ".text.$1" 614} 615 616assert_not_patched() 617{ 618 out_sections | grep -q "[[:space:]]$(re_quote ".text.$1")[[:space:]]" && 619 fail "function '$1' should not have been cloned" 620 return 0 621} 622 623# section_relocs <section> 624# 625# The relocations against one section. readelf prints every relocation section 626# in turn, so a test asking about ".smp_locks" has to cut its block out of the 627# listing first. 628section_relocs() 629{ 630 local sec="${1//./\\.}" 631 632 out_relocs | awk "/rela$sec'/,/^\$/" 633} 634 635assert_reloc_sym() 636{ 637 section_relocs "$1" | awk -v n="$2" '$5 == n' | grep -q . || 638 fail "expected a relocation to '$2' in '$1'" 639} 640 641assert_no_reloc_sym() 642{ 643 section_relocs "$1" | awk -v n="$2" '$5 == n' | grep -q . && 644 fail "unexpected relocation to '$2' in '$1'" 645 return 0 646} 647 648# assert_reloc_count <section> <count> 649# 650# Counts relocation entries, not header or blank lines: whether a special 651# section entry was extracted once, twice or not at all is usually the whole 652# question. 653# 654# A count of zero is ambiguous on its own -- a section with no relocations and 655# no section at all both read as zero -- so require the section to exist. A 656# test expecting nothing there wants assert_no_section. 657assert_reloc_count() 658{ 659 local n 660 661 assert_section "$1" 662 663 n="$(section_relocs "$1" | grep -cE '^[0-9a-f]{8,}')" 664 [ "$n" = "$2" ] || 665 fail "expected $2 relocations in '$1', found $n" 666} 667 668# assert_klp_sym <symbol> [object] 669# 670# A klp symbol is named .klp.sym.<object>.<symbol>,<sympos>. The object 671# defaults to any, since most tests care that the reference was converted at 672# all rather than which object it resolved against. 673assert_klp_sym() 674{ 675 out_symbols | grep -q "\.klp\.sym\.${2:-[^.]*}\.$(re_quote "$1")," || 676 fail "expected klp symbol for '$1'" 677} 678 679# assert_klp_sympos <symbol> <sympos> 680# 681# The number after the comma in .klp.sym.<object>.<symbol>,<sympos> says which 682# of several same-named symbols livepatch should resolve to, counting from 1; 683# 0 means the name is unique and no disambiguation is needed. Resolving to the 684# wrong one is not a load failure, it is a patch quietly wired to the wrong 685# object. 686assert_klp_sympos() 687{ 688 out_symbols | grep -qE "\.klp\.sym\.[^.]+\.$(re_quote "$1"),$2([[:space:]]|\$)" || 689 fail "expected klp symbol for '$1' with sympos $2, found:$( 690 out_symbols | grep -o "\.klp\.sym\.[^.]*\.$(re_quote "$1"),[0-9]*" | 691 sort -u | tr '\n' ' ')" 692} 693 694assert_no_klp_sym() 695{ 696 out_symbols | grep -q "\.klp\.sym\.${2:-[^.]*}\.$(re_quote "$1")," && 697 fail "unexpected klp symbol for '$1'" 698 return 0 699} 700 701assert_tombstone() 702{ 703 out_symbols | grep -qE "\.klp\.tombstone\.$(re_quote "$1")([[:space:]]|\$)" || 704 fail "expected a tombstone for '$1'" 705} 706 707assert_symbol() 708{ 709 out_symbols | awk -v n="$1" '$NF == n' | grep -q . || 710 fail "expected symbol '$1' in output" 711} 712 713assert_no_symbol() 714{ 715 out_symbols | awk -v n="$1" '$NF == n' | grep -q . && 716 fail "unexpected symbol '$1' in output" 717 return 0 718} 719 720# assert_diff_log <regex> 721# 722# klp diff's combined output, for tests asserting on a diagnostic. Error 723# messages are part of the interface when the whole point is that a construct 724# gets rejected, and a rejection for the wrong reason is not a pass. 725assert_diff_log() 726{ 727 diff_log | grep -qE -- "$1" || 728 fail "expected '$1' in klp diff output: $(tail -2 "$workdir/diff.log")" 729} 730 731# checksum_of <object> <symbol> 732# 733# The checksum "klp checksum" recorded for one symbol, as a hex string. 734# 735# .discard.sym_checksum is an array of { u64 addr; u64 checksum; }, where addr 736# is the target of a relocation naming the symbol. Nothing in the section 737# itself says which symbol an entry belongs to, so the relocation is what 738# locates the entry; the checksum is the eight bytes after it. 739# Callers use this in a command substitution, where fail() would only exit the 740# subshell and the test would carry on with an empty checksum. So this returns 741# non-zero and prints nothing, and the assertions below check for that. For 742# the same reason it does not run run_checksum() itself: that one does call 743# fail(), and from in here the message would be captured as the checksum 744# rather than ending the test. The caller runs it first. 745checksum_of() 746{ 747 local obj="$workdir/$1" sym="$2" off 748 749 off="$($READELF -rW "$obj" 2>/dev/null | 750 awk -v s="$sym" '/rela\.discard\.sym_checksum/,/^$/ { 751 if ($5 == s) { print $1; exit } 752 }')" 753 754 [ -n "$off" ] || return 1 755 756 $OBJCOPY -O binary --only-section=.discard.sym_checksum \ 757 "$obj" "$workdir/checksums.bin" 2>/dev/null || return 1 758 759 dd if="$workdir/checksums.bin" bs=1 skip=$((16#$off + 8)) count=8 \ 760 status=none | od -An -tx1 | tr -d ' \n' 761} 762 763# assert_checksum_differs <symbol> / assert_checksum_matches <symbol> 764# 765# Compare what klp checksum recorded for a symbol in the original against the 766# patched object. This is what decides whether klp diff treats a function as 767# changed, so a test asserting only that the right functions were cloned cannot 768# tell a correct checksum from one which happens to differ. 769checksum_pair() 770{ 771 run_checksum 772 773 orig_checksum="$(checksum_of "$orig_obj" "$1")" 774 patched_checksum="$(checksum_of "$patched_obj" "$1")" 775 776 [ -n "$orig_checksum" ] || 777 fail "no checksum recorded for '$1' in $orig_obj" 778 [ -n "$patched_checksum" ] || 779 fail "no checksum recorded for '$1' in $patched_obj" 780} 781 782assert_checksum_differs() 783{ 784 checksum_pair "$1" 785 786 [ "$orig_checksum" != "$patched_checksum" ] || 787 fail "checksum for '$1' unchanged at $orig_checksum, expected it to differ" 788} 789 790assert_checksum_matches() 791{ 792 checksum_pair "$1" 793 794 [ "$orig_checksum" = "$patched_checksum" ] || 795 fail "checksum for '$1' changed from $orig_checksum to" \ 796 "$patched_checksum, expected no change" 797} 798 799# run_post_link [expected exit status] 800# 801# klp post-link runs last in a livepatch build, converting the intermediate 802# __klp_relocs.* sections into the .klp.rela.* form the kernel consumes. It 803# needs nothing but an object containing those sections, which is what klp diff 804# produces, so it runs on out.o here rather than on a built module. Rewrites 805# out.o in place, so the out_* helpers show the result afterwards. 806run_post_link() 807{ 808 local expect="${1:-0}" rc=0 809 810 "$OBJTOOL" klp post-link "$workdir/out.o" \ 811 > "$workdir/post-link.log" 2>&1 || rc=$? 812 813 [ "$rc" = "$expect" ] || 814 fail "klp post-link exited $rc, expected $expect:" \ 815 "$(tail -2 "$workdir/post-link.log")" 816} 817 818# The flags readelf prints for a section, or nothing when it has none. The 819# leading "[nn]" index is stripped first so the columns can be counted. 820section_flags() 821{ 822 out_sections | sed 's/^ *\[[ 0-9]*\] *//' | 823 awk -v s="$1" '$1 == s && $7 ~ /^[A-Za-z]+$/ { print $7 }' 824} 825 826# assert_section_flag <section> <letter> 827# 828# SHF_RELA_LIVEPATCH is OS-specific, so readelf renders it as "o". A klp rela 829# section which lost it is an ordinary rela section, which the linker may apply 830# and the livepatch code will not. 831assert_section_flag() 832{ 833 local flags; flags="$(section_flags "$1")" 834 835 [ -n "$flags" ] || 836 fail "section '$1' has no flags, expected '$2'" 837 case "$flags" in 838 *"$2"*) ;; 839 *) fail "section '$1' has flags '$flags', expected '$2'" ;; 840 esac 841} 842 843# assert_klp_rela <object> <section> 844# 845# post-link names the converted sections .klp.rela.<object>.<section>, one per 846# base section. Also checks SHF_RELA_LIVEPATCH, since the name alone is not 847# what makes the kernel process it. 848assert_klp_rela() 849{ 850 local name=".klp.rela.$1.$2" 851 852 out_sections | grep -q "[[:space:]]$(re_quote "$name")[[:space:]]" || 853 fail "expected section '$name' in output" 854 855 assert_section_flag "$name" o 856} 857 858# assert_livepatch_sym <symbol> 859# 860# Symbols a klp relocation resolves against live in SHN_LIVEPATCH, which 861# readelf prints as "OS [0xff20]" -- llvm-readelf without the space, so match 862# either. The kernel resolves these itself at patch load; anything else is a 863# symbol the module loader will try, and fail, to resolve normally. 864assert_livepatch_sym() 865{ 866 out_symbols | grep -E 'OS ?\[0xff20\]' | 867 grep -qE "\.klp\.sym\.[^.]+\.$(re_quote "$1")," || 868 fail "expected a klp symbol for '$1' in SHN_LIVEPATCH" 869} 870