Read the kernel's own source files - #59
Merged
Merged
Conversation
Adds kxray.source: six modules for the text files a kernel ships with, and the context hash that stops a citation going quietly stale. Grounded on five real files out of the pinned 7.2.2 tarball, committed under corpora/source/pinned so the parsers have something to run against in CI and in a notebook that has downloaded nothing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
kxray.source, the last unbuilt row of the toolkit in M1. Everything else inkxrayreads what a running kernel printed. This reads what the kernel ships as text: MAINTAINERS, the syscall tables, Kconfig files, and the source itself.Six modules, all measured against real files rather than written from memory.
The tree handle
tree.pyanswers one question before anything else asks a second one: how much kernel is here. There are three honest answers on a machine somebody is sitting at.The full tree is the 1.6 GB
./kxbox/kernel/tree.shunpacks, checksum verified. The partial tree is five files committed undercorpora/source/pinned/, so the parsers work in CI and in a notebook that has downloaded nothing. Nothing at all is a fresh checkout, and the right answer there is the command that fixes it.Tree.completeis the field to read first. On the corpus a lookup that misses says the file is not in the corpus, never that it is not in the kernel. Those are different sentences and only one of them is true.MAINTAINERS is 29847 lines, so the corpus has
MAINTAINERS.excerpt. The suffix is the mechanism rather than a label.read("MAINTAINERS")finds it and setspartialon what it hands back, andparse_filecarries that onto theMaintainers, so being a slice travels with the content instead of living in a comment somebody has to remember.The MAINTAINERS glob is not fnmatch
This is the one worth reading twice.
FILESYSTEMS (VFS and infrastructure) carries
F: fs/*.The kernel's own header block says a single star stops at a slash and a double star crosses one.
fs/proc/base.cbelongs to PROC FILESYSTEM, and the VFS section said so by writing one star instead of a trailing slash. A tool built onfnmatchmails every patch underfs/to the VFS maintainers and looks right while it does it.Two more from the same file, both confirmed against
scripts/get_maintainer.plrather than assumed.K:patterns are applied with perl's/x, at lines 575 and 622 of the script. So AUDIT SUBSYSTEM's\baudit_[a-z_0-9]\+\bhas a literal plus sign in it and does not matchaudit_log_start. It matchesaudit_l+x. That is a fact about the file rather than a bug here, and it is a test so nobody helpfully fixes it.THE REST carries
F: *andF: */, so it matches every file in Linux. Any lookup that takes the first hit and stops reports Linus for the whole kernel.lookupreturns everything in file order andspecificis the same list with the catch-all removed.PROC FILESYSTEM has a status of Maintained, two mailing lists and no
M:line at all, socontactsfalls through to the lists. Coming back empty would read as nobody looks after this, and the file does not say that.Write is 4 here and 1 there
A syscall number with no architecture attached is not an identifier. The pinned box is 32 bit, so every number a lesson prints comes out of
syscall_32.tbl, and a reader on their own laptop comparing against the numbers they know finds different ones. Both tables are committed so that can be a table rather than a claim.number_ofreturns None when a name appears under two abis rather than picking the first. Nineteen rows in the 32 bit table have a name and no entry point, which is a number reserved forever so a binary from 1994 gets ENOSYS rather than somebody else's system call. Two rows carry a literal-in the compat column holding the place open so thatnoreturnlands in the right one.Why a .config has symbols nobody chose
CONFIG_PREEMPT=ygives a build withCONFIG_PREEMPT_BUILD=yandCONFIG_PREEMPTION=yin it as well.kernel/Kconfig.preemptis the whole explanation and it is 194 lines.Six of the fifteen symbols in that file have a type and no prompt, which means they never appear in
menuconfigand cannot be set by hand at all. In a.configthey look exactly like something a person picked.The parser had two unparsed lines at first, the
defaultlines that belong to thechoiceblock rather than to any symbol. That grew aChoicedataclass rather than the number being written down as acceptable. Fourth time in this project a parser was fixed instead of a baseline.Three names for one call
No two of them equal, with a macro standing between each pair. Grepping
fs/read_write.cforsys_writeis worse than finding nothing: it finds lines 728 and 750, bothksys_write, which is a different function that the real entry point calls. The reader lands three lines from what they wanted, on something close enough to be believed.That last paragraph is a correction. The first draft of the module docstring said the string does not appear in the file at all, which was written from memory and is false. Running it found
ksys_write, and the true version is a better fact than the one that was wrong.unwrapstrips the wrappers, which are a list rather than a rule because they are architecture dependent. The same call is__ia32_sys_writeon the pinned box and__x64_sys_writeon the reader's laptop.The context hash
A citation here names a file and a piece of text to find in it, never a line number, and that already survived files moving. What it did not survive is the anchor holding still while the code under it changes.
An anchor is usually a function signature. The signature is the most stable line in a function and the body underneath is the part people edit. So a citation supporting a sentence about what a function does goes stale with the anchor sitting exactly where it always was, the checker stays green, and the lesson is wrong.
So a confirmed citation now records a hash of the seven lines around its anchor. Proved end to end by poking one line inside a window in the unpacked tree:
"Still there and changed" is a different sentence from "gone" and needs a different answer from a reader, so it is a separate finding.
The hash is over whitespace normalised lines, which is a deliberate choice about what counts as a change. Reindenting a block and tab to space churn do not fire. Renaming a variable, adding a branch or changing an argument do. Hashing the bytes gives a checker that cries every release and gets switched off, which is worse than not having one.
All 73 citations in the repository picked one up from a single
--confirmrun against the pinned tree, and no line number moved.tests/test_refcheck.pynow asserts every confirmed citation carries one.What is committed
100K of corpus, all out of the tarball rather than off a running kernel, so it lives in
corpora/source/rather than beside the traces.Plus
corpora/proc/tier0/kallsyms-write.txt, eight lines off the running box, which is where the third name comes from. It is markednot-abi, because the closing section ofDocumentation/ABI/READMEnames kernel symbols as something that must not under any circumstances be considered stable.Baseline goes from 32 artefacts and 1982 lines to 38 and 5224. Every reader accounts for every line and nothing is unparsed.
read_write.chas no reader on purpose.symbolsopens it with a name to look for, so there is no whole file count to take, and saying so beats inventing one.Where the models live
Per module rather than in
kxray/models.py, which is 1424 lines already. The/proctypes belong there because widgets, the baseline and each other all share them. A syscall table row is only ever a syscall table row, the same waykxray/btf/format.pykeeps its own. The reasoning is written down inkxray/source/__init__.pyso the next person does not have to guess.Checks
43 new tests in
tests/test_source.py, 6 more intests/test_refcheck.py, whole suite green. Every gate green: ruff, pytest, node, diagrams, nbbuild, sitebuild, kxbox, vendor, baseline, claimledger, coverage, bpc, kconfig, refcheck, lintnb, kxmanim, lintprose.Closes the
kxray.sourcerow in #2.