Answers the question directly in docs/licensing.md §6, because "LDLS runs
Linux drivers" reads like it contradicts §2 and does not.
LDLS is Apache-2.0. Every file under ldls/ is ours; the loader came from the
ELF-64 gABI and the x86-64 psABI. The licence of LDLS and the licence status
of what happens at run time are two different questions and only the first is
about us:
ldls/ Apache-2.0 distributed by us
a .ko GPL-2.0 distributed by the user's distro
the two in one process -- distributed by nobody
GPLv2 §0 says where its obligations attach -- "the act of running the Program
is not restricted" -- so no combined work is distributed by anyone and no
obligation is triggered. Same position FreeBSD has shipped from for a decade.
Stated honestly in the same section: the *user* cannot redistribute the
combination either, which is why RAMDISK_EXCLUDE exists and why .gitignore
refuses *.ko.
EXPORT_SYMBOL_GPL was left open in the plan; it is now answered and the answer
is cleaner than expected. That marking gates *Linux's own* symbols. Every
symbol LDLS provides is ours, reimplemented from facts, so there is no gate
being bypassed because no Linux symbol is being exposed. LDLS implements no
licence check -- it reads the declared licence and prints it before loading
anything.
And the sharpest edge in rule 3 mostly goes away. The uncomfortable row was
struct layouts, which a compiled driver indexes by offset, so the shim must
reproduce them exactly -- and a field-for-field match looks like transcription
even when it is not. It does not have to be in our source: kernels built with
CONFIG_DEBUG_INFO_BTF publish /sys/kernel/btf/vmlinux, and that carries both
the layouts and the function prototypes as generated type data about the
kernel the user already has. Verified on this machine: struct pci_dev field by
field, and FUNC 'pci_iomap' with its FUNC_PROTO. LDLS reads them at load time
on the user's machine; our source contains neither.
That also mostly dissolves rule 4, since BTF describes the kernel that is
actually installed rather than one pinned by guessing. What BTF does not give
is behaviour -- what napi_complete_done *does* is still ours to write from
documentation, and that is the whole of the real work.
Also adds the SPDX header ldls/ko.h was missing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
docs/plan/ldls.md milestone L0. ldls/ko.c indexes the sections of an ELF64
relocatable object, places the allocatable ones, resolves undefined symbols
against a caller's table and applies the relocations. Nothing is executed.
It is freestanding -- no libc, no allocation, no I/O -- so the same source
builds as a host tool now and as the SchOS-side host later. That is the
arrangement mkschfs and the kernel already share, and for the same reason:
the failures at this layer are format failures, and one found on the host
costs a second instead of a boot.
$ ldls-inspect 8139too.ko
module 8139too
license GPL
loads to 33988 bytes
relocations: 1980
R_X86_64_64 363, PC32 991, PLT32 428, 32S 169, PC64 29
undefined symbols: 94
stops at: unresolved: __fentry__
The licence is printed before anything is loaded, because it is the one
property that decides whether the object may be on the machine at all and it
is a plain string in .modinfo. Rule 1 is easier to keep when the answer is on
screen.
94 symbols is the measured API surface of 8139too on 6.18.46 -- the list,
exactly, rather than an estimate -- and it is L1's work queue. It is smaller
than it looks: __fentry__, __stack_chk_fail, __ref_stack_chk_guard,
__x86_return_thunk and __fortify_panic are compiler and instrumentation
artefacts that stub out in a line each.
Swept over every module in a stock 6.18.46 tree: 2,440 objects, all of them
laid out and relocated to completion, none with a relocation type the loader
does not handle. That sweep is also what retired the fixed section table --
nvidia-modeset has 7,069 sections and 74,305 relocations, against a median of
50 -- so the caller supplies the table and there is no limit to run into
rather than a generous one that fails later.
Loading is not running, and the doc says so: not one symbol is implemented,
and the distance between "relocates" and "transmits a packet" is the rest of
the plan.
No .ko is in this tree and .gitignore now refuses one outright. make
ldls-check runs 18 checks against ldls/test/refmod.c, which is ours, written
to contain one of each thing the loader has to get right.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2