commit ea2106c74490e26a040f0f3a2bd040e78dd0df0c
parent d782f95f24aa25035b6f67ce3b7508ce4562886c
Author: Jared Tobin <jared@jtobin.io>
Date: Tue, 20 Oct 2026 12:25:26 +0400
merge impl/objects: a taint run kept to the objects, the version exported
`vestigia run` and `read` take --object, keeping sites in objects
whose path contains the given text, as `diff` keeps its origins, and
traceOf takes `objects` as diffOf does. nix/lib.nix exports the
version the cabal file declares, so a consumer pinning vestigia
reads it rather than parsing the cabal file itself.
Diffstat:
7 files changed, 47 insertions(+), 15 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -23,4 +23,8 @@
its getrandom included, seeded. A taint run that marked no
secret is refused.
* `traceOf` and `diffOf` run either as a derivation;
- `nix/lib.nix` holds them for any package set.
+ `nix/lib.nix` holds them for any package set, with the version
+ the command reports.
+ * `--object` keeps a taint run's sites (`run`, `read`, and
+ `traceOf`'s `objects`) to objects whose path contains the given
+ text, as it keeps a differential run's origins.
diff --git a/README.md b/README.md
@@ -76,7 +76,9 @@ Here the modulus compares in decoding the secret scalar, its
canonicality check, and the double-and-add of the scalar
multiplication, which iterates about 245 times per call on the
secret's bits. `vestigia read FILE.xml` gives the same report from a
-memcheck run made elsewhere.
+memcheck run made elsewhere. `--object TEXT` keeps the sites in
+objects whose path contains the given text, as it keeps a
+differential run's origins.
### Differential traces: `vestigia record` and `vestigia diff`
@@ -142,10 +144,11 @@ origins.
The flake's `lib.<system>` holds `traceOf` and `diffOf`, which run a
harness under either instrument as a derivation: a run for
`x86_64-linux` then executes on whatever builds for that system, and
-its report is cached like any other output. `diffOf` repeats the
-first run as its control. `nix/lib.nix` holds the same definitions
-for one package set, for a consumer that pins vestigia and builds
-traces with its own nixpkgs.
+its report is cached like any other output. Either takes `objects`,
+the texts `--object` is given. `diffOf` repeats the first run as its
+control. `nix/lib.nix` holds the same definitions for one package
+set, for a consumer that pins vestigia and builds traces with its own
+nixpkgs, beside `version`, the version the command reports.
```nix
vestigia.lib.x86_64-linux.diffOf {
diff --git a/app/Main.hs b/app/Main.hs
@@ -38,7 +38,7 @@ import Vestigia.Layout (fixLayout)
import Vestigia.Memcheck (readMemcheck)
import Vestigia.Symbol (symbolize)
import Vestigia.Trace
- (readObjects, trace, traceJson, traceSummary, withObjects)
+ (readObjects, sitesIn, trace, traceJson, traceSummary, withObjects)
data Opts = Opts {
oValgrind :: !(Maybe FilePath)
@@ -82,8 +82,8 @@ usage e = do
hPutStrLn stderr $ unlines
[ "usage:"
, " vestigia run [--valgrind PATH] [--xml FILE] [--out FILE] \
- \-- PROGRAM [ARG...]"
- , " vestigia read [--out FILE] FILE.xml"
+ \[--object TEXT]... -- PROGRAM [ARG...]"
+ , " vestigia read [--out FILE] [--object TEXT]... FILE.xml"
, " vestigia record [--qemu PATH] [--plugin PATH] --dump FILE \
\-- PROGRAM [ARG...]"
, " vestigia diff [--out FILE] [--addr2line PATH] \
@@ -94,6 +94,7 @@ usage e = do
, "branch and address that depended on bytes the program marked"
, "secret (vestigia.h), and writes the report (vestigia/trace-v1)."
, "valgrind is --valgrind, else $VESTIGIA_VALGRIND, else on PATH."
+ , "--object keeps sites in objects whose path contains TEXT."
, ""
, "record executes PROGRAM under QEMU with vestigia's plugin and"
, "dumps its leakage trace per instruction; diff compares dumps"
@@ -209,7 +210,7 @@ report o exit os xml = do
hPutStrLn stderr ("vestigia: " <> xml <> ": " <> e)
exitWith (ExitFailure 2)
Right mc -> do
- let tr = withObjects os (trace mc)
+ let tr = sitesIn (oObjects o) (withObjects os (trace mc))
doc = encode
(traceJson (T.pack (showVersion version)) exit tr)
maybe (TIO.putStr doc) (\p -> TIO.writeFile p doc) (oOut o)
diff --git a/flake.nix b/flake.nix
@@ -32,7 +32,7 @@
};
lib = {
- inherit (v) traceOf diffOf valgrindDev;
+ inherit (v) traceOf diffOf valgrindDev version;
};
checks.default = hpkgs.vestigia;
diff --git a/lib/Vestigia/Trace.hs b/lib/Vestigia/Trace.hs
@@ -22,6 +22,7 @@ module Vestigia.Trace (
, Site(..)
, Trace(..)
, trace
+ , sitesIn
, withObjects
, readObjects
, objectOffset
@@ -118,6 +119,18 @@ trace mc = Trace {
grouped = M.fromListWith (flip (<>))
[ ((c, frIp top), [ (top, e) ]) | ((c, top), e) <- tagged ]
+-- | Only the sites in objects whose path contains one of the given
+-- texts, as a differential run keeps its origins; every site when
+-- none is given.
+sitesIn :: [T.Text] -> Trace -> Trace
+sitesIn ts tr
+ | null ts = tr
+ | otherwise = tr { trSites = filter inside (trSites tr) }
+ where
+ inside s = case frObj (siFrame s) of
+ Just o -> any (`T.isInfixOf` o) ts
+ Nothing -> False
+
-- | The trace with the harness's map of its objects, by which each
-- frame is named by its address in its object.
withObjects :: [(Integer, T.Text)] -> Trace -> Trace
diff --git a/nix/lib.nix b/nix/lib.nix
@@ -72,17 +72,19 @@ let
'';
# one harness run under memcheck, as a derivation: its report,
- # memcheck's XML, and what the harness printed. A harness that
+ # memcheck's XML, and what the harness printed. `objects` keeps
+ # sites in objects whose path contains one of them. A harness that
# fails still leaves a report of what ran; a run vestigia could
# not read fails the build.
- traceOf = { name, harness, args ? [ ] }:
+ traceOf = { name, harness, args ? [ ], objects ? [ ] }:
pkgs.runCommand "vestigia-trace-${name}" { } ''
mkdir -p $out
start=$(date +%s%N)
set +e
${vestigia}/bin/vestigia run \
--xml $out/memcheck.xml --out $out/trace.json \
- -- ${harness} ${lib.escapeShellArgs args} \
+ ${lib.concatMapStrings (o: "--object ${lib.escapeShellArg o} ")
+ objects}-- ${harness} ${lib.escapeShellArgs args} \
> $out/stdout 2> $out/stderr
echo $? > $out/status
set -e
@@ -139,8 +141,11 @@ let
runs}2> $out/summary
echo $(( ($(date +%s%N) - start) / 1000000 )) > $out/milliseconds
'';
+ # the version the cabal file declares, which the command reports
+ version = builtins.head (builtins.match ".*\nversion: *([0-9.]+).*"
+ (builtins.readFile (src + "/vestigia.cabal")));
in
{
- inherit hpkgs vestigia plugin include traceOf diffOf;
+ inherit hpkgs vestigia plugin include traceOf diffOf version;
valgrindDev = valgrind.dev;
}
diff --git a/test/Main.hs b/test/Main.hs
@@ -108,6 +108,12 @@ traceTests = testGroup "trace"
@?= Just 0x401000
objectOffset os (f "/lib/libc.so.6" 0x7000) @?= Nothing
+ , testCase "a site is kept to the objects named" $ do
+ tr <- trace <$> fixture "probe.xml"
+ length (trSites (sitesIn [ "probe" ] tr)) @?= 2
+ trSites (sitesIn [ "libc" ] tr) @?= []
+ length (trSites (sitesIn [] tr)) @?= 2
+
, testCase "one site per instruction, whatever called it" $ do
tr <- trace <$> either assertFailure pure (readMemcheck twoCallers)
fmap (\s -> (frIp (siFrame s), siCount s, length (siStacks s)))