// SPDX-License-Identifier: GPL-2.0-or-later // // The loader's test object. **Ours, on purpose.** // // docs/architecture/ldls.md rule 1 says nothing GPL ever enters an image we build, and // the same rule applies to the tree itself: there is no `.ko` committed here // and there never will be. So the thing `make ldls-check` loads is this file, // compiled with `-c`, which produces exactly what a `.ko` is -- an ELF64 // relocatable object for x86-64. // // It is written to contain one of each thing the loader has to get right, // because a test object that only exercises the easy path is a test that // passes on a loader that does not work: // // - undefined symbols, of both the function and the data kind // - a `.text` with calls needing PC32/PLT32 // - `.data` with an absolute pointer needing R_X86_64_64 // - `.rodata` a pointer points into, so section-relative values matter // - `.bss`, which must arrive zeroed and is NOBITS with no file content // - a `.modinfo` shaped the way a module's is, so ko_modinfo() is exercised // // It is never linked and never run. Compiling it is the whole of its job. // Things this object does not define. A real module's undefined list is // hundreds of names from the kernel it was built against; five is enough to // prove the loader reports them rather than to pretend this is a driver. extern int ldls_test_alloc(unsigned long size); extern void ldls_test_free(void *p); extern int ldls_test_print(const char *s); extern int ldls_test_counter; // undefined *data*, not a function // .rodata, and something in .data pointing at it -- which is the case that // needs a section-relative symbol value to come out right. static const char greeting[] = "ldls reference module"; const char *ldls_test_greeting = greeting; // .bss. The loader must zero this rather than copy it, because NOBITS has no // bytes in the file to copy. static char scratch[256]; char *ldls_test_scratch = scratch; // .data with a known value, so a test can check the bytes survived layout. int ldls_test_magic = 0x1D15; // .text with calls, which is where PC32 and PLT32 come from. int ldls_test_entry(void) { int n = ldls_test_alloc(sizeof(scratch)); if (n == 0) return -1; ldls_test_print(greeting); ldls_test_counter++; scratch[0] = (char)ldls_test_magic; ldls_test_free(scratch); return ldls_test_counter; } // A second function, called by the first, so at least one relocation resolves // inside the object and does not need the resolver at all. int ldls_test_twice(void) { return ldls_test_entry() + ldls_test_entry(); } // Shaped like a module's `.modinfo`: NUL-terminated key=value strings in their // own section. A real one is produced by MODULE_LICENSE() and friends; this is // the same bytes by hand, because the macros that emit them are not ours. #define MODINFO __attribute__((section(".modinfo"), used, aligned(1))) MODINFO static const char mi_license[] = "license=GPL"; MODINFO static const char mi_description[] = "description=LDLS loader test object"; MODINFO static const char mi_name[] = "name=refmod"; // Modules define this; ko_name() looks for it to tell a kernel module from an // ordinary object file. int __this_module; // The entry point, under the name `module_init(x)` gives it. // // L1 calls this, so it is written to exercise the thing L1 is for: a sequence // of calls out to symbols this object does not define, in an order that can be // checked. Three calls, always the same three, always in this order -- which // is exactly what a real driver's init produces and what no amount of reading // the symbol table would tell you. // // It deliberately does *not* dereference what the stubs return. A real driver // does, faults, and that is a useful result; a test that faults every time is // a test that cannot tell a fault it expected from one it did not. int init_module(void) { ldls_test_print(greeting); ldls_test_alloc(sizeof(scratch)); ldls_test_free(scratch); return 0; }