xref: /linux/tools/objtool/Documentation/klp-test-design.txt (revision 5b6dca02b3e2254d2fd5706d76d7ab4610a67296)
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