commit c6911c285ec337df8733870c7e5c434aceb1ea26
parent 83a5e59a7681a797cd5315696d88f163c43dfbad
Author: Jared Tobin <jared@jtobin.io>
Date: Sat, 31 Oct 2026 13:22:12 +0400
merge impl/object-paths: objects resolved to the files they name
read resolves the objects a harness reports to the files they name,
as memcheck names a frame's object, so a library linked by soname has
its sites placed by offset.
Diffstat:
5 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -18,6 +18,9 @@
* `record` appends the guest's ISA to its dump.
* `diffOf` takes a `contract`; the command finds LLVM's
`llvm-objdump` through `$VESTIGIA_OBJDUMP`.
+ * `read` resolves the objects a harness reports to the files they
+ name, as memcheck names a frame's object, so a library reached by
+ its soname's link has its sites placed by offset.
- 0.1.0 (2026-10-22)
* Initial version, with two instruments over a harness that marks
diff --git a/app/Main.hs b/app/Main.hs
@@ -54,7 +54,8 @@ import Vestigia.Layout (fixLayout)
import Vestigia.Memcheck (Memcheck, readMemcheck)
import Vestigia.Symbol (symbolize)
import Vestigia.Trace
- (Taint(..), readObjects, sitesIn, trace, traceJson, traceSummary)
+ (Taint(..), readObjects, resolveObjects, sitesIn, trace, traceJson,
+ traceSummary)
data Opts = Opts {
oValgrind :: !(Maybe FilePath)
@@ -289,7 +290,7 @@ markedObjects p = do
\no secret (vestigia_secret was never called on any bytes); \
\its run says nothing")
exitWith (ExitFailure 2)
- Right os -> pure os
+ Right os -> resolveObjects os
readXml :: FilePath -> IO Memcheck
readXml xml = do
diff --git a/lib/Vestigia/Trace.hs b/lib/Vestigia/Trace.hs
@@ -33,16 +33,19 @@ module Vestigia.Trace (
, trace
, sitesIn
, readObjects
+ , resolveObjects
, objectOffset
, traceJson
, traceSummary
, classText
) where
+import Control.Exception (IOException, try)
import qualified Data.List as L
import qualified Data.Map.Strict as M
import qualified Data.Text as T
import Numeric (readHex, showHex)
+import System.Directory (canonicalizePath, doesPathExist)
import Vestigia.Json
import Vestigia.Memcheck
@@ -189,6 +192,23 @@ readObjects = traverse line . filter (not . T.null . T.strip) . T.lines
-- | A frame's address in its object, where the harness reported the
-- object: by its path, else by its file name.
+-- | A run's objects, each path resolved to the file it names, as
+-- memcheck names a frame's object: a loader reaches a library by
+-- the link its soname names, memcheck by the file the link leads
+-- to. A path that names nothing here, as in a report made
+-- elsewhere, is kept as reported.
+resolveObjects :: [(Integer, T.Text)] -> IO [(Integer, T.Text)]
+resolveObjects = traverse resolve
+ where
+ resolve (b, p) = do
+ let path = T.unpack p
+ here <- doesPathExist path
+ if not here then pure (b, p) else do
+ r <- try (canonicalizePath path)
+ pure (b, either (keep p) T.pack r)
+ keep :: T.Text -> IOException -> T.Text
+ keep p _ = p
+
objectOffset :: [(Integer, T.Text)] -> Frame -> Maybe Integer
objectOffset os f = do
obj <- frObj f
diff --git a/test/Main.hs b/test/Main.hs
@@ -9,6 +9,8 @@ import qualified Data.Map.Strict as M
import qualified Data.Set as S
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
+import System.Directory
+import System.FilePath ((</>))
import Test.Tasty
import Test.Tasty.HUnit
@@ -108,6 +110,23 @@ traceTests = testGroup "trace"
@?= Just 0x401000
objectOffset os (f "/lib/libc.so.6" 0x7000) @?= Nothing
+ , testCase "an object reached by a link is named by its file" $ do
+ tmp <- getTemporaryDirectory
+ let dir = tmp </> "vestigia-resolve-objects"
+ file = dir </> "liba.so.1.2.3"
+ link = dir </> "liba.so.1"
+ removePathForcibly dir
+ createDirectoryIfMissing True dir
+ writeFile file ""
+ createFileLink "liba.so.1.2.3" link
+ real <- T.pack <$> canonicalizePath file
+ os <- resolveObjects
+ [ (0x4000000, T.pack link), (0, "/nowhere/bin/harness") ]
+ removePathForcibly dir
+ os @?= [ (0x4000000, real), (0, "/nowhere/bin/harness") ]
+ objectOffset os (Frame 0x4000010 (Just real) Nothing Nothing Nothing)
+ @?= Just 0x10
+
, testCase "a site is kept to the objects named" $ do
tr <- one <$> fixture "probe.xml"
length (trSites (sitesIn [ "probe" ] tr)) @?= 2
diff --git a/vestigia.cabal b/vestigia.cabal
@@ -44,6 +44,7 @@ library
base >= 4.9 && < 5
, bytestring
, containers
+ , directory
, process
, text
@@ -78,6 +79,8 @@ test-suite vestigia-tests
base
, bytestring
, containers
+ , directory
+ , filepath
, tasty
, tasty-hunit
, text