kxray.corpus: load a pinned capture, and take the run out of it - #62
Merged
Conversation
Two halves of one job, in two modules because they are used at different moments. index.py is loading. The routing table moved here out of tools/baseline.py, so the tool that opens all thirty nine artefacts and a lesson that wants to open one now go through the same table. An artefact is asked for by id, which is its path under corpora/ with the suffix dropped, and comes back with its metadata already loaded and the name of the reader that opens it. read() runs that reader, handing the /proc readers the kernel path out of the artefact's own metadata, which is the part everybody who opened one of those by hand kept getting wrong. normalize.py is the substitution that makes two captures comparable. The process happened to be pid 41 this time and pid 2792 last time, the trace happened to start three seconds after boot, and the mutex happened to live at c78250b8. Replace all of that consistently and what is left is the part that is about the kernel. The legend says what every name stood for, because a normalised trace nobody can take back to the machine it came off is not evidence. Two properties hold it up, and the tests for them run over every artefact in the corpus rather than over a fixture: the line count never changes, and normalising twice is the same as normalising once. Sorting is off unless asked for. It is right for an event trace where every line stands alone and wrong for a function_graph trace where the order of the lines is the shape of the call tree. The pointer rule is the one heuristic here and it errs in the safe direction. A bare eight digit run has to have a hex letter in it to count as an address, because eight decimal digits look the same and the kernel prints plenty of those. Written 0x, or in a range like the pairs in /proc/self/maps, it counts either way. A number that was not renamed is visible; a size renamed to ptr#4 is a difference nobody would ever see. tools/baseline.py keeps only the comparison against corpora/BASELINE.toml, which is the part of it that is about the baseline rather than about the corpus. Its numbers do not move: 39 artefacts, 7837 lines, 0 unparsed. python3 -m kxray.corpus list, show and normalize are there for the moment before writing a rule, which is running it and reading the output next to the original.
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.
The M1 row that reads
kxray.corpus: loading, plus the normalisation that makes any of this diffable.Two halves of one job, in two modules, because they get used at different moments. Load first, normalise second, compare third.
Loading
The routing table has moved out of
tools/baseline.pyand intokxray/corpus/index.py. That is the change that made the package worth having. Until now the only thing that knew which reader opens which artefact was the baseline tool, and a lesson that wanted to open one capture had to work it out again by hand, which meant two answers to the same question that could drift apart without anybody noticing.An artefact is asked for by id, which is its path under
corpora/with the suffix dropped. It comes back with its metadata already loaded and the name of the reader that opens it.traces/tier0/write-1byterather than something shorter because that is the name every lesson, blueprint and test in this repository already uses. A shorter id would have bought nothing and cost a migration, plus a period where two names for the same file were both correct.read()hands the/procreaders the kernel path out of the artefact's own metadata, which is the part everybody opening one of those by hand kept getting wrong. What a file is called on disk does not decide how it is read or what it is worth:self-maps.txtis/proc/self/maps, and only the second of those two names reaches the stability ledger.Routing on the file name looks like the sort of thing that breaks the first time somebody names a file badly. It is held up by the thing that depends on it: an artefact nothing claims raises, the baseline fails, CI goes red. A file cannot land in
corpora/and be read by nothing.Normalising
The process happened to be pid 83138 this time. The trace happened to start three seconds after boot. The mutex happened to live at
c78250b8. Every one of those changes on the next run, so a comparison of two captures of the same work reports several hundred differences and none of them is the one anybody wanted to know about.The legend is half the output and is not optional, because a normalised trace that cannot say which process
pid#3was is a trace nobody can take back to the machine it came off.Six rules, in the order the specification puts them, and the order is load bearing twice. Pointers run before offsets, because
__mutex_lock+0x8c/0x230has hex in it that is not an address. Identity runs before cpu, because a task column holds a pid and a cpu column holds a cpu and telling them apart is done by where they are and not by what they look like.The two properties, checked over the whole corpus
Both tests are parametrised over every artefact in
corpora/rather than over a fixture. A rule is a regular expression and a regular expression is wrong in ways nobody predicts, so running all of them over all of the files is the only check here that catches a rule doing something to a file its author never opened.It never changes the number of lines. Normalising is a substitution and not an edit. A rule that dropped a line or wrapped one would make the result impossible to read next to the original, and reading the two next to each other is how anybody checks a rule at all.
Running it twice is the same as running it once. A rule that matches its own output keeps renaming things every pass, and a file that changes every time you look at it is not a baseline.
What it deliberately does not do
It does not reorder anything by default. Rule seven in the specification sorts concurrent events by a stable key. That is right for an event trace where every line stands alone, and wrong for a
function_graphtrace where the order of the lines is the shape of the call tree. Soorderexists, it is off unless asked for by name, and sorting a call graph is a mistake this will not make on your behalf.It does not guess at what might vary. Every pattern was written against a line that is in
corpora/, with one exception, which is the counter rule, and that exception says so in its own comment rather than being hidden.The one heuristic, and which way it fails
Eight hex digits and eight decimal digits are indistinguishable when none of the digits happens to be a letter, and the kernel prints plenty of eight digit decimals that are not addresses.
utimeout of/proc/self/statis one.So a bare run has to contain a hex letter to count as an address. Written
0xit counts either way, and a range like the address pairs in/proc/self/mapscounts either way, which is how08048000-08149000still comes out asptr#1-ptr#2.What that gives up is the occasional real address whose digits are all decimal and which is neither in a range nor written
0x. That is the direction to fail in. A number that was not renamed is sitting there in the output where anybody can see it. A size that was renamed toptr#4is a difference nobody will ever see.The command line
normalizeis for the moment before writing a rule: run it, read the output next to the original, and see whether the substitution did what it claimed. That reading is the whole check on a rule, so it is worth being one command. Nothing here writes anything.What moved and what did not
tools/baseline.pykeeps only the comparison againstcorpora/BASELINE.toml, which is the part of it that was ever about the baseline rather than about the corpus. Its numbers are unchanged: 39 artefacts, 7837 lines, 0 unparsed.The full gate is green. 1449 passed, 7 skipped, up from 1394.