12ab23a58SSong Liu.. SPDX-License-Identifier: GPL-2.0 22ab23a58SSong Liu 32ab23a58SSong Liu====================================== 42ab23a58SSong LiuDesign of the objtool klp test harness 52ab23a58SSong Liu====================================== 62ab23a58SSong Liu 72ab23a58SSong Liutools/objtool/tests/ holds unit tests for the klp subcommands of 82ab23a58SSong Liuobjtool -- ``klp checksum``, ``klp diff``, ``klp post-link`` and 92ab23a58SSong Liu``--klp-symids`` -- which together turn two builds of the kernel into a 102ab23a58SSong Liulivepatch module. 112ab23a58SSong Liu 122ab23a58SSong LiuThis document explains how the harness is built and why. For the rules to 132ab23a58SSong Liufollow when adding a test, see klp-write-tests.txt. 142ab23a58SSong Liu 152ab23a58SSong Liu 162ab23a58SSong LiuTL;DR 172ab23a58SSong Liu===== 182ab23a58SSong Liu 192ab23a58SSong LiuOne run covers one compiler and one architecture; CI runs the combinations. 202ab23a58SSong LiuBuild objtool first -- it needs libelf and libxxhash -- and the same ARCH is 212ab23a58SSong Liuused for both steps. 222ab23a58SSong Liu 232ab23a58SSong LiuNatively, with gcc:: 242ab23a58SSong Liu 252ab23a58SSong Liu make -C tools/objtool 262ab23a58SSong Liu make -C tools/objtool tests 272ab23a58SSong Liu 282ab23a58SSong LiuNatively, with clang -- LLVM=1 additionally selects the LLVM binutils:: 292ab23a58SSong Liu 302ab23a58SSong Liu CC=clang make -C tools/objtool tests 312ab23a58SSong Liu LLVM=1 make -C tools/objtool tests 322ab23a58SSong Liu 332ab23a58SSong LiuCross, with gcc -- an arm64 host running the x86 tests:: 342ab23a58SSong Liu 352ab23a58SSong Liu ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- make -C tools/objtool 362ab23a58SSong Liu ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- make -C tools/objtool tests 372ab23a58SSong Liu 382ab23a58SSong LiuCross, with clang. It defaults to the host triple however it is invoked, so 392ab23a58SSong Liu--target= is what makes it emit x86; OBJCOPY is needed because BFD's is 402ab23a58SSong Liuusually built for the host's target alone:: 412ab23a58SSong Liu 422ab23a58SSong Liu ARCH=x86_64 make -C tools/objtool 432ab23a58SSong Liu ARCH=x86_64 CC="clang --target=x86_64-linux-gnu" OBJCOPY=llvm-objcopy \ 442ab23a58SSong Liu make -C tools/objtool tests 452ab23a58SSong Liu 462ab23a58SSong LiuA run ends with a totals line; anything other than fail:0 is a real result:: 472ab23a58SSong Liu 482ab23a58SSong Liu # pass:48 fail:0 static-skip:1 probe-skip:0 xfail:0 xpass:0 492ab23a58SSong Liu 502ab23a58SSong LiuUseful extras:: 512ab23a58SSong Liu 522ab23a58SSong Liu tools/objtool/tests/run-tests.sh basic # one test, by name 532ab23a58SSong Liu tools/objtool/tests/run-tests.sh --keep basic # and keep what it built 542ab23a58SSong Liu 552ab23a58SSong Liu 562ab23a58SSong LiuWhy unit tests are possible at all 572ab23a58SSong Liu================================== 582ab23a58SSong Liu 592ab23a58SSong Liuklp-build is a pipeline: build the kernel twice, checksum both, diff them, 602ab23a58SSong Liulink the result. Testing that end to end means two kernel builds per case, 612ab23a58SSong Liuwhich is too slow to run often and too heavy to keep in the tree. 622ab23a58SSong Liu 632ab23a58SSong LiuThree properties make a much cheaper test possible. 642ab23a58SSong Liu 652ab23a58SSong Liu**objtool has no configuration-dependent logic.** It never reads ``.config``. 662ab23a58SSong LiuEvery ``CONFIG_`` string in its source is a comment or one error message, and 672ab23a58SSong Liuits only build-time conditionals are driven by host libraries and the target 682ab23a58SSong Liuarchitecture. Configuration reaches objtool through exactly two channels: the 692ab23a58SSong Liu``objtool-args-$(CONFIG_*)`` lines in scripts/Makefile.lib, and the 702ab23a58SSong Liucontents of the object handed to it. 712ab23a58SSong Liu 722ab23a58SSong Liu**The klp subcommands use none of the first channel.** Of objtool's options 732ab23a58SSong Liuthey consult three -- ``checksum``, ``debug_checksum``, ``dryrun`` -- all from 742ab23a58SSong Liutheir own command line. So klp behaviour varies with configuration *only* 752ab23a58SSong Liuthrough the input object. 762ab23a58SSong Liu 772ab23a58SSong Liu**Therefore a test can reproduce any configuration's behaviour by reproducing 782ab23a58SSong Liuits input.** Compile a small freestanding fixture with the flags that 792ab23a58SSong Liuconfiguration would have used, and objtool cannot tell the difference. No 802ab23a58SSong Liukernel, no ``.config``, no object cache. 812ab23a58SSong Liu 822ab23a58SSong LiuThe whole suite runs in a few seconds. 832ab23a58SSong Liu 842ab23a58SSong Liu 852ab23a58SSong LiuShape of a test 862ab23a58SSong Liu=============== 872ab23a58SSong Liu 882ab23a58SSong LiuEach test compiles one fixture twice -- once plain, once with ``-DPATCHED`` -- 892ab23a58SSong Liuruns ``klp checksum`` over both, diffs them, and asserts on properties of the 902ab23a58SSong Liuoutput object:: 912ab23a58SSong Liu 922ab23a58SSong Liu . "$(dirname "$0")/../lib.sh" 932ab23a58SSong Liu 942ab23a58SSong Liu setup 952ab23a58SSong Liu build_pair basic.c 962ab23a58SSong Liu 972ab23a58SSong Liu assert_input_symbol changed 982ab23a58SSong Liu run_diff 992ab23a58SSong Liu 1002ab23a58SSong Liu assert_patched changed 1012ab23a58SSong Liu assert_not_patched untouched 1022ab23a58SSong Liu 1032ab23a58SSong Liu pass "changed function cloned, unchanged function left alone" 1042ab23a58SSong Liu 1052ab23a58SSong LiuAssertions check properties, never recorded output. Codegen varies between 1062ab23a58SSong Liucompilers and versions, so a golden file would report churn rather than 1072ab23a58SSong Liuregressions. 1082ab23a58SSong Liu 1092ab23a58SSong Liu 1102ab23a58SSong LiuLayout 1112ab23a58SSong Liu====== 1122ab23a58SSong Liu 1132ab23a58SSong Liu:: 1142ab23a58SSong Liu 1152ab23a58SSong Liu tools/objtool/tests/ 1162ab23a58SSong Liu lib.sh the harness: everything a test may call 1172ab23a58SSong Liu run-tests.sh selects, runs and classifies 1182ab23a58SSong Liu generic/ 1192ab23a58SSong Liu test-*.sh 1202ab23a58SSong Liu fixtures/*.c 1212ab23a58SSong Liu x86/ 1222ab23a58SSong Liu test-*.sh 1232ab23a58SSong Liu fixtures/*.c 1242ab23a58SSong Liu 1252ab23a58SSong LiuWhich architecture a test is for is expressed by where it lives. The runner 1262ab23a58SSong Liuexecutes ``generic/`` plus the directory matching this architecture, so a test 1272ab23a58SSong Liuwhich cannot apply is not run rather than running in order to report that it 1282ab23a58SSong Liudid not. There is no ``x86_only`` helper, and no lookup letting an 1292ab23a58SSong Liuarchitecture fixture shadow a generic one: an architecture-specific test 1302ab23a58SSong Liucarries its own fixtures. 1312ab23a58SSong Liu 1322ab23a58SSong LiuCompilers cannot be expressed the same way, because CI varies ``CC`` over the 1332ab23a58SSong Liusame tree. A compiler requirement stays a declaration inside the test 1342ab23a58SSong Liu(``gcc_only``, ``clang_only``). 1352ab23a58SSong Liu 1362ab23a58SSong Liu 1372ab23a58SSong LiuThe environment is established once 1382ab23a58SSong Liu=================================== 1392ab23a58SSong Liu 1402ab23a58SSong LiuSourcing lib.sh runs ``klp_preflight``, which checks that objtool 1412ab23a58SSong Liuexists and has klp support, that ``$CC`` works, that the binutils are present, 1422ab23a58SSong Liuand which architecture this is. The answers are exported, so: 1432ab23a58SSong Liu 1442ab23a58SSong Liu* ``run-tests.sh`` sources lib.sh too, and therefore knows the 1452ab23a58SSong Liu architecture before it chooses which tests to run; 1462ab23a58SSong Liu* each test inherits the answers rather than repeating the work; 1472ab23a58SSong Liu* a test run on its own establishes them for itself. 1482ab23a58SSong Liu 1492ab23a58SSong LiuPreflight answers only whether the suite can run at all. A suite which cannot 1502ab23a58SSong Liurun must not exit 0 looking like one which passed, so a missing objtool fails 1512ab23a58SSong Liuthe whole run with a TAP ``Bail out!`` rather than skipping each test in turn. 1522ab23a58SSong LiuWhat a *particular* compiler can do is a different question, left to the test 1532ab23a58SSong Liuwhich cares. 1542ab23a58SSong Liu 1552ab23a58SSong Liu 1562ab23a58SSong LiuOutcomes 1572ab23a58SSong Liu======== 1582ab23a58SSong Liu 1592ab23a58SSong LiuOutput is TAP. The distinction the harness cares most about is between kinds 1602ab23a58SSong Liuof skip, because a skip is how a suite quietly stops testing anything: 1612ab23a58SSong Liu 1622ab23a58SSong Liu``declared`` 1632ab23a58SSong Liu The test said in advance it does not apply -- ``gcc_only`` on a clang run. 1642ab23a58SSong Liu Expected indefinitely. 1652ab23a58SSong Liu 1662ab23a58SSong Liu``probe`` 1672ab23a58SSong Liu The construct did not turn up in the built object this time. Weaker: one 1682ab23a58SSong Liu which becomes permanent is a fixture that has stopped testing anything. 1692ab23a58SSong Liu 1702ab23a58SSong Liu``undeclared`` 1712ab23a58SSong Liu Counted as a **failure**. A test which gives up for a reason it never 1722ab23a58SSong Liu declared is a hole, not an outcome. 1732ab23a58SSong Liu 1742ab23a58SSong Liu``xfail``/``xpass`` come with them, so a known failure is reported rather than 1752ab23a58SSong Liucommented out, and one which starts passing says so instead of going quietly 1762ab23a58SSong Liugreen. 1772ab23a58SSong Liu 1782ab23a58SSong LiuThe runner classifies the TAP result line, not everything a test printed: 1792ab23a58SSong Liuobjtool warns on stderr and that output is captured, so a stray line ahead of 1802ab23a58SSong Liuthe result would otherwise leave the exit status to decide -- and an expected 1812ab23a58SSong Liufailure exits 0. 1822ab23a58SSong Liu 1832ab23a58SSong LiuA run ends with a totals line:: 1842ab23a58SSong Liu 1852ab23a58SSong Liu # pass:48 fail:0 static-skip:1 probe-skip:0 xfail:0 xpass:0 1862ab23a58SSong Liu 1872ab23a58SSong Liuand reports what it left out:: 1882ab23a58SSong Liu 1892ab23a58SSong Liu # not run: 5 tests in x86/ (this run is arm64) 1902ab23a58SSong Liu 1912ab23a58SSong Liu 1922ab23a58SSong LiuWorking directories 1932ab23a58SSong Liu=================== 1942ab23a58SSong Liu 1952ab23a58SSong LiuA run gets one directory; each test gets a subdirectory of it, mirroring the 1962ab23a58SSong Liusource layout:: 1972ab23a58SSong Liu 1982ab23a58SSong Liu /tmp/klp-tests.XXXXXXXX/ 1992ab23a58SSong Liu generic/test-basic/{orig.o,patched.o,out.o,Module.symvers,...} 2002ab23a58SSong Liu x86/test-kcfi/... 2012ab23a58SSong Liu 2029b11acaaSJoe LawrenceBy default (``KEEP=failed``) only failing tests keep their directories; the 2039b11acaaSJoe Lawrencerunner reports where they are. ``KEEP=all`` keeps every test's directory; 2049b11acaaSJoe Lawrence``KEEP=none`` removes them all. The runner ``rmdir``s the run directory when 2059b11acaaSJoe Lawrenceit is empty -- which fails if anything was left behind unexpectedly, so a test 2069b11acaaSJoe Lawrencewhich dies without cleaning up is reported rather than silently leaking. 2072ab23a58SSong Liu 2082ab23a58SSong Liu 2092ab23a58SSong LiuRunning 2102ab23a58SSong Liu======= 2112ab23a58SSong Liu 2122ab23a58SSong Liu:: 2132ab23a58SSong Liu 2142ab23a58SSong Liu make -C tools/objtool # needs libelf and libxxhash 2152ab23a58SSong Liu make -C tools/objtool tests 2162ab23a58SSong Liu 2172ab23a58SSong Liu CC=clang make -C tools/objtool tests # the other toolchain 2182ab23a58SSong Liu LLVM=1 make -C tools/objtool tests # and its binutils too 2192ab23a58SSong Liu 2209b11acaaSJoe Lawrence make -C tools/objtool tests KEEP=all # keep every test's workdir 2219b11acaaSJoe Lawrence make -C tools/objtool tests KEEP=none # remove all workdirs 2229b11acaaSJoe Lawrence 2239b11acaaSJoe Lawrence tools/objtool/tests/run-tests.sh basic # one test; failures kept by default 2242ab23a58SSong Liu 2252ab23a58SSong LiuA run covers one compiler and one architecture; CI runs the combinations. 2262ab23a58SSong Liu 2272ab23a58SSong LiuCross-compiled runs 2282ab23a58SSong Liu------------------- 2292ab23a58SSong Liu 2302ab23a58SSong Liuobjtool klp is built only where ARCH_HAS_KLP is set, which today means x86 -- 2312ab23a58SSong Liuso an arm64 machine cannot run any of this natively. It can run all of it 2322ab23a58SSong Liucross, because objtool is a host tool that only reads and rewrites ELF, and 2332ab23a58SSong Liuthe tests only compile fixtures and inspect the objects. Nothing has to 2342ab23a58SSong Liuexecute target code. 2352ab23a58SSong Liu 2362ab23a58SSong Liu:: 2372ab23a58SSong Liu 2382ab23a58SSong Liu ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- make -C tools/objtool 2392ab23a58SSong Liu ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- make -C tools/objtool tests 2402ab23a58SSong Liu 2412ab23a58SSong Liuobjtool itself stays a native binary: it is built with HOSTCC, not CC, so 2422ab23a58SSong Liusetting a cross compiler cannot produce one the host is unable to run. ARCH 2432ab23a58SSong Liuselects both the objtool target and the directory of tests to run. 2442ab23a58SSong Liu 2452ab23a58SSong Liuclang needs telling, since it defaults to the host triple however it is 246*913bf39fSJoe Lawrenceinvoked. LLVM=1 with CROSS_COMPILE does that for you -- the --target= it 247*913bf39fSJoe Lawrencederives is forwarded to the tests -- and the fixtures include no kernel 248*913bf39fSJoe Lawrenceheaders, so no sysroot is needed: 249*913bf39fSJoe Lawrence 250*913bf39fSJoe Lawrence:: 251*913bf39fSJoe Lawrence 252*913bf39fSJoe Lawrence ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- LLVM=1 \ 253*913bf39fSJoe Lawrence make -C tools/objtool tests 254*913bf39fSJoe Lawrence 255*913bf39fSJoe LawrenceNaming the compiler by hand works too, and is what to reach for when the 256*913bf39fSJoe Lawrencetarget triple is not the one CROSS_COMPILE implies: 2572ab23a58SSong Liu 2582ab23a58SSong Liu:: 2592ab23a58SSong Liu 2602ab23a58SSong Liu ARCH=x86_64 CC="clang --target=x86_64-linux-gnu" \ 2612ab23a58SSong Liu OBJCOPY=llvm-objcopy make -C tools/objtool tests 2622ab23a58SSong Liu 2632ab23a58SSong LiuCROSS_COMPILE picks the binutils, and each can be overridden on its own. 2642ab23a58SSong Liureadelf reads any target and rarely needs overriding; BFD's objcopy is usually 2652ab23a58SSong Liubuilt for the host's alone, hence OBJCOPY=llvm-objcopy above, or install 2662ab23a58SSong Liubinutils-multiarch. 2672ab23a58SSong Liu 2682ab23a58SSong LiuEither readelf will do. The assertions read readelf's output, and the two 2692ab23a58SSong Liuspell some of it differently -- GNU prints "OS [0xff20]" for SHN_LIVEPATCH 2702ab23a58SSong Liuwhere llvm-readelf prints "OS[0xff20]" -- so they accept both. 2712ab23a58SSong Liu 2722ab23a58SSong LiuGetting this wrong is easy and the harness refuses rather than producing a 2732ab23a58SSong Liumisleading result. "CC=clang ARCH=x86_64" alone selects the x86 tests and 2742ab23a58SSong Liuthen builds arm64 objects; preflight compiles a probe object, hands it to 2752ab23a58SSong Liuobjtool, and stops the run if they disagree about the architecture, or if 2762ab23a58SSong LiuARCH does not match what the compiler emits. 2772ab23a58SSong Liu 2782ab23a58SSong Liu 2792ab23a58SSong LiuWhat this does not cover 2802ab23a58SSong Liu======================== 2812ab23a58SSong Liu 2822ab23a58SSong LiuThese are unit tests for objtool's klp subcommands. They do not build a 2832ab23a58SSong Liukernel, do not run scripts/livepatch/klp-build, and do not load a 2842ab23a58SSong Liulivepatch. Behaviour which only appears when the kernel applies a patch -- 2852ab23a58SSong Liuthe module loader refusing a relocation, late module patching ordering -- has 2862ab23a58SSong Liuto be tested by booting, and is out of scope here. 287