<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>nu1lptr - Static Analysis</title>
    <subtitle>Learner &#x2F;&#x2F; Cybersecurity Ph.D.@UMich CSE &#x2F;&#x2F; Photographer</subtitle>
    <link rel="self" type="application/atom+xml" href="https://shengtuo.me/tags/static-analysis/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://shengtuo.me"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-09-13T18:00:00-07:00</updated>
    <id>https://shengtuo.me/tags/static-analysis/atom.xml</id>
    <entry xml:lang="en">
        <title>Beyond a Single Bitcode File</title>
        <published>2026-09-13T18:00:00-07:00</published>
        <updated>2026-09-13T18:00:00-07:00</updated>
        
        <author>
          <name>
            Shengtuo Hu
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://shengtuo.me/blog/beyond-single-bitcode-file/"/>
        <id>https://shengtuo.me/blog/beyond-single-bitcode-file/</id>
        
        <content type="html" xml:base="https://shengtuo.me/blog/beyond-single-bitcode-file/">&lt;h2 id=&quot;tl-dr&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tl-dr&quot; aria-label=&quot;Anchor link for: tl-dr&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
TL;DR&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;rllvm&lt;&#x2F;code&gt; used to produce one answer: a merged whole-program &lt;code&gt;.bc&lt;&#x2F;code&gt; file. Version
0.5 can instead inventory the modules first, keep their identities and known
provenance in a catalog, select the ones an analysis needs, and only then copy,
archive, or merge them. It can acquire those modules from a wrapped build or
regenerate selected C and C++ compilations from &lt;code&gt;compile_commands.json&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The original wrapper workflow still works. It now sits inside a larger model:
&lt;strong&gt;acquire, catalog, select, materialize&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-bc-file-was-only-the-first-output&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-bc-file-was-only-the-first-output&quot; aria-label=&quot;Anchor link for: the-bc-file-was-only-the-first-output&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
The &lt;code&gt;.bc&lt;&#x2F;code&gt; file was only the first output&lt;&#x2F;h2&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;shengtuo.me&#x2F;blog&#x2F;whole-program-bitcode&#x2F;&quot;&gt;my previous post&lt;&#x2F;a&gt;, I described &lt;code&gt;rllvm&lt;&#x2F;code&gt; as the
third tool in the &lt;code&gt;wllvm&lt;&#x2F;code&gt; and &lt;code&gt;gllvm&lt;&#x2F;code&gt; lineage: replace the compiler, build
normally, then recover one LLVM module from the linked program. I also wrote that
there was little urgency to switch if either older tool already worked for you.&lt;&#x2F;p&gt;
&lt;p&gt;That remains fair for the narrow job of producing one &lt;code&gt;.bc&lt;&#x2F;code&gt; file. It no longer
describes the whole project.&lt;&#x2F;p&gt;
&lt;p&gt;A merged module is useful, but merging is a poor first step. It collapses module
boundaries before a consumer can decide what belongs in an analysis. It also
hides useful distinctions: two compilations of the same source can use different
flags, a missing module is different from an unsupported one, and a module found
in an executable says something different from one regenerated from a compilation
database.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;rllvm&lt;&#x2F;code&gt; 0.5 makes the unmerged modules addressable. The whole-program file becomes
one possible output rather than the only interface.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;modules-before-merging&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#modules-before-merging&quot; aria-label=&quot;Anchor link for: modules-before-merging&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Modules before merging&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;rllvm-info --json&lt;&#x2F;code&gt; now inventories bitcode, objects, executables, regular
archives, and existing catalogs without merging anything:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#31333d;color:#ffffffc4;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#a3cbe3;&quot;&gt;rllvm-info&lt;&#x2F;span&gt;&lt;span&gt; app&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt; --json &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db7c6d;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; catalog.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each catalog entry has an opaque module ID and a content hash. Where available,
it also records source associations, target and data layout, compilation
configuration, debug-information presence, and diagnostics. A module can be
&lt;code&gt;available&lt;&#x2F;code&gt;, &lt;code&gt;missing&lt;&#x2F;code&gt;, &lt;code&gt;unsupported&lt;&#x2F;code&gt;, or &lt;code&gt;failed&lt;&#x2F;code&gt;; failure does not erase the
other evidence.&lt;&#x2F;p&gt;
&lt;p&gt;The catalog is deliberately careful about what it does not know. Finding a
source filename in debug information does not prove which compiler produced it.
Finding several modules in an archive does not prove that they form a complete
program. Those fields stay empty, and whole-program completeness stays unknown.&lt;&#x2F;p&gt;
&lt;figure class=&quot;substrate-fig substrate-acquire&quot; aria-label=&quot;Two acquisition paths feed a module catalog: a wrapped build provides link membership, while a compilation database provides compilation configurations from the current source tree&quot;&gt;
&lt;div class=&quot;substrate-sources&quot;&gt;
&lt;div class=&quot;substrate-card&quot;&gt;
&lt;span class=&quot;substrate-kicker&quot;&gt;live build&lt;&#x2F;span&gt;
&lt;strong&gt;object · archive · binary&lt;&#x2F;strong&gt;
&lt;small&gt;which modules reached the link&lt;&#x2F;small&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;substrate-card&quot;&gt;
&lt;span class=&quot;substrate-kicker&quot;&gt;recorded build&lt;&#x2F;span&gt;
&lt;strong&gt;compile_commands.json&lt;&#x2F;strong&gt;
&lt;small&gt;how each source was compiled&lt;&#x2F;small&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;substrate-down&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;&#x2F;span&gt;&lt;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
&lt;div class=&quot;substrate-catalog&quot;&gt;
&lt;span class=&quot;substrate-kicker&quot;&gt;shared representation&lt;&#x2F;span&gt;
&lt;strong&gt;module catalog&lt;&#x2F;strong&gt;
&lt;small&gt;identity · integrity · provenance · uncertainty&lt;&#x2F;small&gt;
&lt;&#x2F;div&gt;
&lt;figcaption&gt;Both paths produce modules and the same catalog format, but they provide different evidence.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;two-kinds-of-build-evidence&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#two-kinds-of-build-evidence&quot; aria-label=&quot;Anchor link for: two-kinds-of-build-evidence&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Two kinds of build evidence&lt;&#x2F;h2&gt;
&lt;p&gt;The wrapper observes a real build. A path recorded in the finished executable is
evidence that the corresponding object participated in that link. This answers
the whole-program question, but the old path section does not record a complete
compiler identity, environment, or source snapshot.&lt;&#x2F;p&gt;
&lt;p&gt;A compilation database answers a different question. It preserves one command
per translation unit, so &lt;code&gt;rllvm-compdb&lt;&#x2F;code&gt; can list those entries and regenerate only
the current-tree modules an analysis asks for:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#31333d;color:#ffffffc4;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#a3cbe3;&quot;&gt;rllvm-compdb&lt;&#x2F;span&gt;&lt;span&gt; list build&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#db7c6d;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; compilations.json
&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#a3cbe3;&quot;&gt;rllvm-compdb&lt;&#x2F;span&gt;&lt;span&gt; generate build&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt; --source&lt;&#x2F;span&gt;&lt;span&gt; src&#x2F;parser.c \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;  --extra-arg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#db7c6d;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-O0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt; --output-dir&lt;&#x2F;span&gt;&lt;span&gt; analysis&#x2F;parser
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The importer keeps duplicate compilations distinct, records the original and
effective arguments, and puts failures beside successful modules. It does not
pretend to reconstruct the historical build. Generated headers must exist now,
the original environment is unknown, and a compile command says nothing about
which executable eventually used its object.&lt;&#x2F;p&gt;
&lt;p&gt;This distinction matters for analysis. Use wrapper capture when linked membership
is the fact you need. Use the compilation database when you want selected,
repeatable analysis compilations from the current tree.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;select-then-materialize&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#select-then-materialize&quot; aria-label=&quot;Anchor link for: select-then-materialize&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Select, then materialize&lt;&#x2F;h2&gt;
&lt;p&gt;Catalogs can be filtered by module ID, source, or known configuration. Alternatives
within one selector are combined; different selector types intersect. An unmatched
selector is an error rather than an empty success.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#31333d;color:#ffffffc4;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#a3cbe3;&quot;&gt;rllvm-get-bc&lt;&#x2F;span&gt;&lt;span&gt; app&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt; --source&lt;&#x2F;span&gt;&lt;span&gt; src&#x2F;parser.c&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt; --output-dir&lt;&#x2F;span&gt;&lt;span&gt; analysis&#x2F;selected
&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#a3cbe3;&quot;&gt;rllvm-get-bc&lt;&#x2F;span&gt;&lt;span&gt; analysis&#x2F;selected&#x2F;catalog.json&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span&gt; parser.bc
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first command copies separate, hash-checked modules into a new directory and
writes the catalog last. Its module paths are relative, so the directory can move
as a unit. The second command chooses to merge that collection. Archive and partial
merge strategies remain available when one large link is the wrong shape.&lt;&#x2F;p&gt;
&lt;figure class=&quot;substrate-fig substrate-materialize&quot; aria-label=&quot;A module catalog is filtered before three possible outputs: a relocatable collection, a bitcode archive, or merged whole-program bitcode&quot;&gt;
&lt;div class=&quot;substrate-modules&quot; aria-label=&quot;catalog modules&quot;&gt;
&lt;span&gt;&lt;b&gt;01&lt;&#x2F;b&gt; parse.c &lt;i&gt;debug&lt;&#x2F;i&gt;&lt;&#x2F;span&gt;
&lt;span&gt;&lt;b&gt;02&lt;&#x2F;b&gt; parse.c &lt;i&gt;release&lt;&#x2F;i&gt;&lt;&#x2F;span&gt;
&lt;span&gt;&lt;b&gt;03&lt;&#x2F;b&gt; lexer.c &lt;i&gt;release&lt;&#x2F;i&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;substrate-dim&quot;&gt;&lt;b&gt;04&lt;&#x2F;b&gt; plugin.c &lt;i&gt;missing&lt;&#x2F;i&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;substrate-filter&quot;&gt;
&lt;span class=&quot;substrate-kicker&quot;&gt;selection&lt;&#x2F;span&gt;
&lt;strong&gt;source + configuration&lt;&#x2F;strong&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;substrate-outputs&quot;&gt;
&lt;span&gt;relocatable&lt;br&gt;&lt;b&gt;collection&lt;&#x2F;b&gt;&lt;&#x2F;span&gt;
&lt;span&gt;bitcode&lt;br&gt;&lt;b&gt;archive&lt;&#x2F;b&gt;&lt;&#x2F;span&gt;
&lt;span&gt;merged&lt;br&gt;&lt;b&gt;.bc&lt;&#x2F;b&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;div&gt;
&lt;figcaption&gt;Selection preserves the useful boundary. Materialization can remain separate or merge only the chosen modules.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;real-builds-are-mostly-edge-cases&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#real-builds-are-mostly-edge-cases&quot; aria-label=&quot;Anchor link for: real-builds-are-mostly-edge-cases&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Real builds are mostly edge cases&lt;&#x2F;h2&gt;
&lt;p&gt;The high-level model works only if acquisition survives actual compiler command
lines. Recent work therefore looks less glamorous and matters just as much.&lt;&#x2F;p&gt;
&lt;p&gt;Response files are expanded for classification while the real compiler still
receives the original arguments. Nested files, quoting, escapes, byte-order marks,
and relative paths follow Clang&#x27;s rules. Commands generated by &lt;code&gt;rllvm&lt;&#x2F;code&gt; switch to
response files automatically when the operating system&#x27;s argument limit would be
too small.&lt;&#x2F;p&gt;
&lt;p&gt;LTO needs separate handling because its “object” may already be bitcode. The
default marker mode covers full and ThinLTO on ELF and Mach-O; save-temps mode can
capture a full-LTO linker&#x27;s optimized module. Rust needs crate-aware markers and
archive updates. Cross-target builds need architecture and sysroot choices to
survive secondary compilations.&lt;&#x2F;p&gt;
&lt;p&gt;eBPF was the pleasant counterexample. An eBPF object built through &lt;code&gt;rllvm-cc&lt;&#x2F;code&gt;
already carried the ordinary &lt;code&gt;.rllvm_bc&lt;&#x2F;code&gt; section. &lt;code&gt;libbpf&lt;&#x2F;code&gt; ignored that section
when loading the program and preserved it when linking objects. Supporting the
target required an integration test and documentation, not a new production
backend. A mechanism that composes with a tool it was not written for is a useful
kind of validation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;measuring-the-tax&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#measuring-the-tax&quot; aria-label=&quot;Anchor link for: measuring-the-tax&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Measuring the tax&lt;&#x2F;h2&gt;
&lt;p&gt;Compiler wrappers are not free. C and C++ normally compile twice: once for the
native object and once for analysis bitcode. &lt;code&gt;rllvm&lt;&#x2F;code&gt; now has a reproducible
workflow harness that validates native behavior and extracted IR before accepting
a timing sample.&lt;&#x2F;p&gt;
&lt;p&gt;The first recorded baseline used an Apple M4, LLVM 22.1.8, eight build jobs, and
three repetitions. Clean build-only time relative to native compilation was:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Workload&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Cache off&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Primed cache&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;nghttp2 C&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.84×&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.61×&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;nghttp2 C++&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.83×&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.20×&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Quiche&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.59×&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.50×&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The cache avoids repeated C&#x2F;C++ bitcode compilation, but still preprocesses and
hashes current inputs before declaring a hit. It does not cache Rust compilation.
The measurements also had an uncontrolled filesystem cache and normal desktop
activity, so they are evidence for these workloads rather than a universal ratio.
They compare &lt;code&gt;rllvm&lt;&#x2F;code&gt; with native builds, not with &lt;code&gt;gllvm&lt;&#x2F;code&gt; or &lt;code&gt;wllvm&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-lineage-now-has-a-fork&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-lineage-now-has-a-fork&quot; aria-label=&quot;Anchor link for: the-lineage-now-has-a-fork&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
The lineage now has a fork&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;wllvm&lt;&#x2F;code&gt;, &lt;code&gt;gllvm&lt;&#x2F;code&gt;, and &lt;code&gt;rllvm&lt;&#x2F;code&gt; still share the same good trick: record sidecar
bitcode paths in object files and let the linker accumulate them. The older tools
center their interface on extracting a merged module or archive. &lt;code&gt;rllvm&lt;&#x2F;code&gt; now keeps
that workflow while adding another acquisition path and a representation between
capture and merge.&lt;&#x2F;p&gt;
&lt;p&gt;That does not make it a strict superset. &lt;code&gt;gllvm&lt;&#x2F;code&gt; supports Fortran and thin
archives; &lt;code&gt;wllvm&lt;&#x2F;code&gt; can drive GCC through dragonegg. But for Clang-based program
analysis, &lt;code&gt;rllvm&lt;&#x2F;code&gt; now exposes a much larger surface: Rust, WebAssembly and eBPF,
real LTO extraction, relocatable paths, validated caching, module catalogs,
selection, and compilation-database imports.&lt;&#x2F;p&gt;
&lt;p&gt;The meaningful difference is no longer implementation language or wrapper speed.
It is where the tool stops. The older workflow stops when it produces bitcode.
&lt;code&gt;rllvm&lt;&#x2F;code&gt; is starting to preserve the structure that the next tool will need.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-comes-next&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-comes-next&quot; aria-label=&quot;Anchor link for: what-comes-next&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
What comes next&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;shengtuo.me&#x2F;blog&#x2F;whole-program-bitcode&#x2F;#what-comes-next&quot;&gt;My previous post&lt;&#x2F;a&gt; ended with a
query interface for coding assistants: definitions, callers, callees,
reachability, possible indirect targets, and an inspectable path back to source.
The roadmap now gives that idea a clearer shape.&lt;&#x2F;p&gt;
&lt;p&gt;The first step is to make program facts easy to ask for. Scripts and coding
assistants should be able to query a catalog in source-level terms and receive
the locations and paths that support each answer. Missing modules, unresolved
calls, and unavailable mappings should remain visible rather than turning into
false certainty.&lt;&#x2F;p&gt;
&lt;p&gt;The second is to make the ask, edit, rebuild, ask loop practical. Unchanged work
should be reused without letting an answer from an older build appear current.
From there, simple reachability can grow into deeper security evidence when a
question needs it, and program facts can be compared across revisions or build
configurations. The useful result is still evidence a person can inspect, not an
automatic verdict.&lt;&#x2F;p&gt;
&lt;p&gt;The final direction is broader reach: following calls across Rust and C&#x2F;C++
boundaries, and carrying a verified analysis snapshot to another machine after
the original build tree is gone.&lt;&#x2F;p&gt;
&lt;p&gt;The progression is from artifacts, to facts, to evidence. Extraction was the
prerequisite. The catalog is the substrate that keeps every later answer tied to
what was actually analyzed and what remains unknown.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;code&gt;rllvm&lt;&#x2F;code&gt; is Apache-2.0 and available on
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;h1994st&#x2F;rllvm&quot;&gt;GitHub&lt;&#x2F;a&gt;. The repository includes the
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;h1994st&#x2F;rllvm&#x2F;blob&#x2F;main&#x2F;docs&#x2F;CATALOG.md&quot;&gt;catalog schema&lt;&#x2F;a&gt; and
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;h1994st&#x2F;rllvm&#x2F;tree&#x2F;main&#x2F;benchmarks&#x2F;baselines&#x2F;2026-09-12-apple-m4&quot;&gt;benchmark evidence&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
