<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>nia.gay</title>
    <subtitle>Notes on systems, software, and whatever else haunts my nightmares.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://nia.gay/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://nia.gay"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-27T00:00:00+00:00</updated>
    <id>https://nia.gay/atom.xml</id>
    <entry xml:lang="en">
        <title>FFI in Miri at 8,000 segfaults&#x2F;sec</title>
        <published>2026-07-27T00:00:00+00:00</published>
        <updated>2026-07-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              nia
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nia.gay/blog/ffi-in-miri/"/>
        <id>https://nia.gay/blog/ffi-in-miri/</id>
        
        <content type="html" xml:base="https://nia.gay/blog/ffi-in-miri/">&lt;figure class=&quot;epigraph&quot;&gt;
  &lt;blockquote&gt;&lt;p&gt;Having written so far, dizziness overwhelms my soul, and tears blind my eyes.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
  
    &lt;figcaption&gt;
      —
      &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;www.yorku.ca&amp;#x2F;inpar&amp;#x2F;alexiad_dawes.pdf&quot;&gt;Anna Komnene, The Alexiad, Preface · trans. Elizabeth A. S. Dawes&lt;&#x2F;a&gt;
    &lt;&#x2F;figcaption&gt;
  
&lt;&#x2F;figure&gt;
&lt;aside class=&quot;provenance-note&quot; role=&quot;note&quot;&gt;
  &lt;p class=&quot;provenance-note__label&quot;&gt;Original talk&lt;&#x2F;p&gt;
  &lt;p class=&quot;provenance-note__stratum&quot; aria-hidden=&quot;true&quot;&gt;stratum II&lt;&#x2F;p&gt;
  &lt;div class=&quot;provenance-note__body&quot;&gt;&lt;p&gt;Herein lies an edited retelling of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&quot;&gt;my RustWeek 2026 talk&lt;&#x2F;a&gt;. I’ve reworked the language to flow as a single article while keeping its argument and most of its damage.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;aside&gt;
&lt;details class=&quot;margin-note margin-note--index&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Talk strata&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;chapter map&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=120s&quot;&gt;The problem with FFI · 02:00&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=250s&quot;&gt;Turning accesses into segfaults · 04:10&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=365s&quot;&gt;Reading the faulting instruction · 06:05&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=540s&quot;&gt;The CI-only race · 09:00&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=730s&quot;&gt;Capstone and yaxpeax · 12:10&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=880s&quot;&gt;Getting allocations back · 14:40&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=1080s&quot;&gt;Synchronizing allocations · 18:00&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=1325s&quot;&gt;Current status · 22:05&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9X-ngiKo_Y0&amp;amp;t=1625s&quot;&gt;Questions from the room · 27:05&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;I used to work on embedded Linux. That’s how I ended up here: one side project led to another until I needed more from Miri, and somewhere along the way I forgot the original project. None of this has much to do with my work a few years ago.&lt;&#x2F;p&gt;
&lt;p&gt;More than anything, this is a personal drama. Life can’t be all code; there needs to be some action. Someone needs to cry, and what better topic to cry about than program verification?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;Miri&lt;&#x2F;a&gt; is an interpreter that executes Rust while tracking enough of the machine state to detect many kinds of undefined behavior. FFI is where execution leaves that model and enters native code Miri cannot see.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-with-ffi&quot;&gt;The problem with FFI&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-problem-with-ffi&quot; aria-label=&quot;Anchor link for: the-problem-with-ffi&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Miri is powerful, but inherently limited—and slow. It’s meant for testing code; you’re not going to play video games on it. As you’ll see, I made that slowness much worse. “8,000 segfaults per second” will eventually need to become hundreds of thousands before this is broadly useful.&lt;&#x2F;p&gt;
&lt;p&gt;The core of the issue is that code spawned in an FFI call can do almost anything, and while it runs, Miri has no idea what it’s doing. That is a problem for an interpreter whose model depends on tracking pointer provenance and whether individual bytes are initialized. How do you preserve that model while executing random nonsense CPU instructions that were once written in C, C++, Java, or anything else?&lt;&#x2F;p&gt;
&lt;p&gt;My answer is that you will it into existence.&lt;&#x2F;p&gt;
&lt;p&gt;We can’t recover &lt;em&gt;everything&lt;&#x2F;em&gt; a precompiled binary does. The concrete goal I set out to achieve is to link an arbitrary &lt;code&gt;.so&lt;&#x2F;code&gt;, call a function, and have it somehow Just Work™ in terms of translating what it actually did to what Miri can understand. Even an incomplete account can constrain the worst case, which is much better than assuming the foreign code touched anything it could possibly reach.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--ledger&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Previously&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;The previous arbitrary-FFI implementation effectively initialized every reachable uninitialized byte and exposed the provenance of every reachable pointer. Nasty stuff.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;That means tracing every memory access: its address and size, and whether it was a read, a write, or both.&lt;&#x2F;p&gt;
&lt;p&gt;Faced with this daunting problem, I sought aid from the holy scripture of Google search results and Stack Overflow. I found a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;19457342&#x2F;trying-to-trap-all-memory-reads-writes-on-a-linux-machine&quot;&gt;random post from 2013 about trapping every memory read and write&lt;&#x2F;a&gt; using &lt;code&gt;SIGSEGV&lt;&#x2F;code&gt;. It can’t be that hard, right?&lt;&#x2F;p&gt;
&lt;p&gt;I wasn’t the first person to have the idea, though perhaps few had tried it in quite this form.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tracing-native-accesses&quot;&gt;Tracing native accesses&lt;a class=&quot;zola-anchor&quot; href=&quot;#tracing-native-accesses&quot; aria-label=&quot;Anchor link for: tracing-native-accesses&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;turning-every-access-into-a-fault&quot;&gt;Turning every access into a fault&lt;a class=&quot;zola-anchor&quot; href=&quot;#turning-every-access-into-a-fault&quot; aria-label=&quot;Anchor link for: turning-every-access-into-a-fault&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Miri &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;child.rs&quot;&gt;forks into two processes&lt;&#x2F;a&gt;. The parent becomes a supervisor; the child remains Miri proper and can jump into whatever foreign code it has been given. Right before it does, we use &lt;code&gt;mprotect&lt;&#x2F;code&gt; to mark the Miri-managed pages exposed to that native call as &lt;code&gt;PROT_NONE&lt;&#x2F;code&gt;. Any access to those pages now raises a segfault.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--ledger&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Portability&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;beyond Linux&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;This implementation is Linux-specific. A macOS port would need to replace &lt;code&gt;ptrace&lt;&#x2F;code&gt;, obtain equivalent mapping information, and contend with the platform’s execution restrictions. That would be plausible, as it’s what a lot of debuggers already need to do; but changing the underlying API would only be the beginning of the work.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;A segfault is only a Unix signal. It is not magic, and execution can continue after one. Signals mean whatever you believe they do, after all. Under &lt;code&gt;ptrace&lt;&#x2F;code&gt;, the supervisor sees the child receive that signal and itself receives a &lt;code&gt;siginfo&lt;&#x2F;code&gt;, including the faulting address.&lt;&#x2F;p&gt;
&lt;p&gt;Great. Amazing. Lovely. Perfect. This all works.&lt;&#x2F;p&gt;
&lt;p&gt;An address is not enough, however. We still need the size of the access, whether it read or wrote, and some way to let the instruction finish. The page is still protected with &lt;code&gt;PROT_NONE&lt;&#x2F;code&gt;; restarted as-is, it would simply fault again.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;decoding-and-replaying-the-instruction&quot;&gt;Decoding and replaying the instruction&lt;a class=&quot;zola-anchor&quot; href=&quot;#decoding-and-replaying-the-instruction&quot; aria-label=&quot;Anchor link for: decoding-and-replaying-the-instruction&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Code is data, so the supervisor reads the bytes at the child’s instruction pointer and hands them to a disassembler. The decoder gives us the possible access width and whether the instruction may read, write, or do both.&lt;&#x2F;p&gt;
&lt;p&gt;This is necessarily conservative. In an RW operand, a write may be conditional on a read, for example. Even so, it gives Miri a much narrower bound on what the instruction could have touched. If the instruction could write, the affected bytes might now be initialized; bytes outside that range definitely were not. When native code reads bytes carrying provenance, Miri can conservatively mark that provenance as exposed.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;mod.rs#L55-L84&quot;&gt;event type is correspondingly small&lt;&#x2F;a&gt;: an address range, an access kind, and—because the decoder sometimes cannot know—a certainty bit for writes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;rust&quot; data-name=&quot;abridged · native_lib&#x2F;mod.rs&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; AccessEvent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    Read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;AccessRange&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;    Write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;AccessRange&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt; `true` when the write is certain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; AccessRange&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    addr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    size&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;details class=&quot;margin-note margin-note--interlude&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Boundary checks&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;what survives&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;Tree Borrows and Stacked Borrows do not translate directly across this boundary. Native execution cannot reproduce the fine-grained events those models need, so at the boundary we use exposed provenance and conservatively allow more aliasing.&lt;&#x2F;p&gt;
&lt;p&gt;These native actions are written back into Miri’s state, so its ordinary validity checks can still reject bad values afterwards. This approach loses some information inside native code, but it does not discard &lt;em&gt;every&lt;&#x2F;em&gt; check around it.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;There’s also the matter that getting the information we need from the decoder is highly architecture-specific. The current implementation uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.capstone-engine.org&#x2F;&quot;&gt;Capstone&lt;&#x2F;a&gt; and supports x86 and x86-64, since these architectures have well-behaved fixed-size accesses on all instructions; other architectures can have register-dependent access widths, such as with ARM scalable vectors.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--interlude&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Decoder archaeology&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;Capstone → yaxpeax&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;Capstone is an excellent disassembler. Unfortunately, I don’t need a disassembler; I need a magic machine that reports an operand’s access behavior and width. Its Rust wrapper also used to make &lt;code&gt;cargo check&lt;&#x2F;code&gt; expensive because the native build still ran; later feature work made that less painful.&lt;&#x2F;p&gt;
&lt;p&gt;I had prototyped something for ARM once, for which I assumed every access was at most 128 bits. Then I learned about how gigantic vector extensions can get and gave up trying for now.&lt;&#x2F;p&gt;
&lt;p&gt;Ixi, at Oxide, had worked on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;yaxpeax-arch&#x2F;latest&#x2F;yaxpeax_arch&#x2F;&quot;&gt;yaxpeax&lt;&#x2F;a&gt; and wondered whether it could do better. I annoyed them until &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iximeow&#x2F;yaxpeax-x86&#x2F;commit&#x2F;87dc48adcce4e80aa98a2867edacc023579fc4c4&quot;&gt;&lt;code&gt;yaxpeax-x86&lt;&#x2F;code&gt; grew the instruction-behavior API I needed&lt;&#x2F;a&gt;, now described in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;yaxpeax-x86&#x2F;latest&#x2F;yaxpeax_x86&#x2F;&quot;&gt;its documentation&lt;&#x2F;a&gt;. The next step is integrating it into Miri to make x86 support less flaky; other architectures remain longer-term work.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;Once we understand the fault, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;parent.rs&quot;&gt;supervisor records its conservative access event&lt;&#x2F;a&gt;. &lt;code&gt;ptrace&lt;&#x2F;code&gt; then lets it rewrite registers and memory in the child.&lt;&#x2F;p&gt;
&lt;p&gt;It diverts the instruction pointer into a fake &lt;code&gt;extern &quot;C&quot;&lt;&#x2F;code&gt; function, moves the stack pointer to zeroed scratch memory, and writes the page address into static storage. That function makes the page readable and writable, then raises &lt;code&gt;SIGSTOP&lt;&#x2F;code&gt; instead of returning.&lt;&#x2F;p&gt;
&lt;p&gt;The supervisor restores the interrupted registers and single-steps the original instruction before sending the child through a matching trampoline that restores &lt;code&gt;PROT_NONE&lt;&#x2F;code&gt;. Execution continues, and the event batch returns to Miri when the FFI call ends.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;parent.rs#L460-L560&quot;&gt;extremely abridged source form&lt;&#x2F;a&gt;, the control loop looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;rust&quot; data-name=&quot;abridged · trace&#x2F;parent.rs&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;new_regs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;set_ip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mempr_off&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;ptrace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;setregs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; new_regs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt; … the child unprotects the page, then stops&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;ptrace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;setregs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; regs_bak&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;ptrace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;step&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt; … run mempr_on, restore the registers, and continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This isn’t a calling convention. I don’t know what it is. It is a crime against computers.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--interlude&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Failure stratum&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;the CI-only race&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;The first tests of this feature passed locally but hung in CI, repeatedly and without useful logs. I eventually, painstakingly, realised the issue was that Unix signals and our IPC messages were racing.&lt;&#x2F;p&gt;
&lt;p&gt;At the start of an FFI call, the child sends its call information to the supervisor. The supervisor now &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;child.rs#L93-L103&quot;&gt;acknowledges that message before the child proceeds&lt;&#x2F;a&gt;. Without the handshake, &lt;code&gt;SIGSTOP&lt;&#x2F;code&gt; could arrive before the IPC message.&lt;&#x2F;p&gt;
&lt;p&gt;The supervisor would then enter the stop-handling path before it knew an FFI call had begun, and the two sides could wait on different channels forever.&lt;&#x2F;p&gt;
&lt;p&gt;Running Miri locally in many-seeds mode made the hang reproducible, and the handshake fixed the ordering bug. Separately, many-seeds testing resulted in me &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;child.rs#L58-L70&quot;&gt;serializing entry into FFI with a mutex&lt;&#x2F;a&gt;: processes running with different seeds can proceed in parallel, but only one can be inside FFI at a time. That both discovered and fixed an outstanding bug when mixing many-seeds and native-lib modes regarding unsynchronized access to foreign statics.&lt;&#x2F;p&gt;
&lt;p&gt;I honest to god fixed a race condition by parallelizing it more. Do you see why I called this a psychological drama?&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;details class=&quot;margin-note margin-note--interlude&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Why not emulate the CPU?&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;Instead of segfault handling, we could use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.qemu.org&#x2F;&quot;&gt;QEMU&lt;&#x2F;a&gt; or write an x86 interpreter. Running the real host code has two advantages: it has a path to speed when native code rarely touches Miri’s memory, and it can call an arbitrary system &lt;code&gt;.so&lt;&#x2F;code&gt; without recreating the host runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine a Vulkan library that mostly works in its own memory and exchanges only a few values with Miri. In principle, this design could one day render something to the screen. Emulating the entire environment would make that much harder, but I am determined to make it so you can indeed play games on your Miri.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;h2 id=&quot;getting-allocations-back-from-native-code&quot;&gt;Getting allocations back from native code&lt;a class=&quot;zola-anchor&quot; href=&quot;#getting-allocations-back-from-native-code&quot; aria-label=&quot;Anchor link for: getting-allocations-back-from-native-code&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Tracing accesses only covers pointers that travel from Miri into native code. Usually, pointers tend to come back as well. To Miri, an address returned by an allocator is otherwise just an integer pretending to be a pointer; Miri cannot know if it may safely dereference it on the host hardware.&lt;&#x2F;p&gt;
&lt;p&gt;So let’s trace allocations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;intercepting-libc&quot;&gt;Intercepting libc&lt;a class=&quot;zola-anchor&quot; href=&quot;#intercepting-libc&quot; aria-label=&quot;Anchor link for: intercepting-libc&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Imagine a function that merely wraps &lt;code&gt;malloc&lt;&#x2F;code&gt;. Miri can shim &lt;code&gt;malloc&lt;&#x2F;code&gt; on the Rust side, but in a precompiled library that wrapper just looks like a random function returning an address. We need to recognize the underlying allocation.&lt;&#x2F;p&gt;
&lt;p&gt;We &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;parent.rs#L395-L404&quot;&gt;place traps at the relevant libc entry points&lt;&#x2F;a&gt;. And by “place traps”, I do mean overwrite their first instruction with a breakpoint:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;rust&quot; data-name=&quot;abridged · trace&#x2F;parent.rs&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;ptrace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;malloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; BREAKPT_INSTR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;ptrace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;calloc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; BREAKPT_INSTR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6A737D, #6A737D);&quot;&gt; …&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;ptrace&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;free&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#005CC5, #79B8FF);&quot;&gt; BREAKPT_INSTR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When native execution reaches one, we &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;parent.rs#L787-L900&quot;&gt;redirect the instruction pointer into one of our fake functions&lt;&#x2F;a&gt;. The original and replacement entry points use the same &lt;code&gt;extern &quot;C&quot;&lt;&#x2F;code&gt; ABI, so the redirect should be ABI-compatible. I did consider shimming all of libc, but was assured that would be excessive. Whatever you say, Ralf.&lt;&#x2F;p&gt;
&lt;p&gt;Does it work?&lt;&#x2F;p&gt;
&lt;p&gt;No. Of course it doesn’t.&lt;&#x2F;p&gt;
&lt;p&gt;Those tiny trampoline shims do not have a normal Miri context, stack, or runtime environment. More importantly, Miri cannot wait until the FFI call returns to learn about an allocation: the native code may use that memory immediately.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;keeping-allocation-events-in-order&quot;&gt;Keeping allocation events in order&lt;a class=&quot;zola-anchor&quot; href=&quot;#keeping-allocation-events-in-order&quot; aria-label=&quot;Anchor link for: keeping-allocation-events-in-order&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;mod.rs#L29-L31&quot;&gt;smuggle a pointer to Miri’s interpreter context through a global&lt;&#x2F;a&gt;, then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;child.rs#L417-L447&quot;&gt;recover it inside the interceptor&lt;&#x2F;a&gt; to process the allocation or deallocation before native execution continues. Sure, that interpreter context type has a lifetime that we just make up in the pointer materialization, but what’s a little &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;nomicon&#x2F;unbounded-lifetimes.html&quot;&gt;unbounded lifetime&lt;&#x2F;a&gt; between friends?&lt;&#x2F;p&gt;
&lt;p&gt;Ordinary access events can be batched until the FFI call returns. Allocation and deallocation break that scheme: one can reuse an address, while the other makes an old address invalid. A pending event may therefore refer to the wrong allocation by the time Miri processes it. Thus we need to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;child.rs#L451-L467&quot;&gt;flush those events before either boundary&lt;&#x2F;a&gt;, using another IPC channel hidden in a global &lt;code&gt;Mutex&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Surely that was it?&lt;&#x2F;p&gt;
&lt;p&gt;Of course not; libc can call itself.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;when-libc-calls-itself&quot;&gt;When libc calls itself&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-libc-calls-itself&quot; aria-label=&quot;Anchor link for: when-libc-calls-itself&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Libc’s internal calls may be inlined or bound directly to private aliases, bypassing the public entry points we patched. Others still reach those breakpoints. If an internal &lt;code&gt;free&lt;&#x2F;code&gt; is redirected while the matching allocation was not, we can end up allocating with one allocator and freeing with the other.&lt;&#x2F;p&gt;
&lt;p&gt;Linux provides the lovely &lt;code&gt;&#x2F;proc&#x2F;self&#x2F;maps&lt;&#x2F;code&gt;, which identifies the object behind each mapping. We use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;parent.rs#L837-L896&quot;&gt;libc’s executable mappings and the saved call-site address&lt;&#x2F;a&gt; to determine whether a call originated inside libc.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--matrix&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;This annoying matrix&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;The bookkeeping has two independent axes:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;question&lt;&#x2F;th&gt;&lt;th&gt;possible states&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;where did the call originate?&lt;&#x2F;td&gt;&lt;td&gt;inside libc &#x2F; outside libc&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;who owns the allocation?&lt;&#x2F;td&gt;&lt;td&gt;libc &#x2F; Miri&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;We must always determine where we fall at runtime, and do so by just staring at pointer and callsite addresses. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;child.rs#L448-L560&quot;&gt;code that routes each call&lt;&#x2F;a&gt; ended up being somewhat simple but straightforwardly hideous.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;Origin is only half the problem; every allocation also needs an owner. A block obtained from real &lt;code&gt;malloc&lt;&#x2F;code&gt; and passed back to Miri must eventually return to libc rather than Miri’s allocator.&lt;&#x2F;p&gt;
&lt;p&gt;This is where I went insane.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--field&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Development conditions&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;circa 04:00&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;Picture me at my desk on the second floor of a little suburban house, very sleep-deprived. It was probably three or four in the morning, though I had only woken a few hours earlier because this had become my schedule.&lt;&#x2F;p&gt;
&lt;p&gt;I was desperate to get &lt;em&gt;something&lt;&#x2F;em&gt; working. This was not nice code. Normal people do not want this merged into their compiler. Who is going to maintain it?&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;Either way, after some headscratching I managed to adapt the above routing code to handle that case as well; and after all of that nonsense, it finally passed CI. The allocation-tracing half still needs cleanup, and its current shape is regrettably split. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;tree&#x2F;alloc-tracing-libc-part-1&quot;&gt;&lt;code&gt;alloc-tracing-libc-part-1&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; installs the interception layer and has its review history in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4792&quot;&gt;PR #4792&lt;&#x2F;a&gt;. The full allocator hand-off lives on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;tree&#x2F;alloc-tracing-libc-part-2&quot;&gt;&lt;code&gt;alloc-tracing-libc-part-2&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which has no PR. The older all-in-one &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4791&quot;&gt;draft PR #4791&lt;&#x2F;a&gt; remains useful archaeology.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--interlude&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Managed runtimes&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;the layer below&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;This mechanism is a low-level fallback, not a specific integration for a managed language like e.g. Java. Managed runtimes typically obtain backing memory through libc or system calls such as &lt;code&gt;mmap&lt;&#x2F;code&gt;; observing those layers recovers allocations or mappings, not the runtime’s object or garbage-collection semantics.&lt;&#x2F;p&gt;
&lt;p&gt;An earlier prototype—effectively part one of this investigation—traces &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;tree&#x2F;alloc-tracing-mmap&quot;&gt;&lt;code&gt;mmap&lt;&#x2F;code&gt; and &lt;code&gt;munmap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; on its own branch; its history is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4622&quot;&gt;draft PR #4622&lt;&#x2F;a&gt;. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;d48a1cc6df19f4b3a0e58cb9b567a8a39082e3b4&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;parent.rs#L480-L524&quot;&gt;syscall handlers themselves are almost offensively direct&lt;&#x2F;a&gt;. Also relevant is &lt;code&gt;brk&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;sbrk&lt;&#x2F;code&gt;; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;d48a1cc6df19f4b3a0e58cb9b567a8a39082e3b4&#x2F;src&#x2F;shims&#x2F;native_lib&#x2F;trace&#x2F;parent.rs#L319-L324&quot;&gt;that’s a problem for later, for the six people who still use it&lt;&#x2F;a&gt;. For this narrow bookkeeping, syscalls are pleasantly easy to intercept with &lt;code&gt;ptrace&lt;&#x2F;code&gt;: record the mapped address and size, and you are mostly done. That prototype worked on the first try and took about twenty minutes, just to make the rest of this story feel worse.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;h2 id=&quot;current-status-and-future-work&quot;&gt;Current status and future work&lt;a class=&quot;zola-anchor&quot; href=&quot;#current-status-and-future-work&quot; aria-label=&quot;Anchor link for: current-status-and-future-work&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The two halves are at different stages. Native access tracing has been merged, and people are already using it; allocation tracing remains experimental branch work. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;README.md#L464-L484&quot;&gt;Miri documentation&lt;&#x2F;a&gt; describes the experimental native-library flags. A minimal invocation looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MIRIFLAGS&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D73A49, #F97583);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt;-Zmiri-native-lib=&#x2F;path&#x2F;to&#x2F;library.so -Zmiri-native-lib-enable-tracing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6F42C1, #B392F0);&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt;  cargo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; +nightly&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; miri&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#032F62, #9ECBFF);&quot;&gt; test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yes, the interface could be nicer. It will be nicer. There is a &lt;em&gt;very&lt;&#x2F;em&gt; big to-do list; please add to it by telling me what needs to improve.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--interlude&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Merge stratum&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;native tracing&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;The original &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4326&quot;&gt;tracing PR&lt;&#x2F;a&gt; was closed rather than merged whole. Its layers landed separately:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4401&quot;&gt;&lt;code&gt;ptrace&lt;&#x2F;code&gt; setup · #4401&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4405&quot;&gt;supervisor · #4405&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4456&quot;&gt;trace incorporation · #4456&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;pull&#x2F;4418&quot;&gt;explicit tracing opt-in · #4418&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;h3 id=&quot;cost-and-coverage&quot;&gt;Cost and coverage&lt;a class=&quot;zola-anchor&quot; href=&quot;#cost-and-coverage&quot; aria-label=&quot;Anchor link for: cost-and-coverage&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The prototype measurement behind the title was roughly 8,000 handled faults per second. Treat that as an order-of-magnitude result, not a reproducible benchmark; this article does not preserve the original machine and workload details.&lt;&#x2F;p&gt;
&lt;p&gt;Because every access to a protected Miri-managed page must fault, it is not fast. This is proof that the approach can work for a toy program, not its final form. Possible optimizations include moving some supervision into a small kernel component and replacing the decoder bottleneck.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--matrix&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Test ledger&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;current limits&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;Merged access tracing has handwritten cases in Miri’s CI. The experimental allocation branch adds its own &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nia-e&#x2F;miri&#x2F;blob&#x2F;8cbb3ee5de59f529e3510715ae0664e2899e22c7&#x2F;tests&#x2F;native-lib&#x2F;pass-dep&#x2F;native_alloc.rs#L10-L50&quot;&gt;ugly boundary tests&lt;&#x2F;a&gt;—for example, allocating through Miri’s Rust-side &lt;code&gt;malloc&lt;&#x2F;code&gt; shim, passing the pointer into native C, and freeing it there.&lt;&#x2F;p&gt;
&lt;p&gt;Broad ecosystem testing is premature while the allocation side remains unfinished. I also do not know how many people already use Miri’s FFI support; probably not many. Yet.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;details class=&quot;margin-note margin-note--field&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;What about a C program?&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;This is not a supported workflow, but a C entry point packaged as a compatible native library could be called through a tiny Rust wrapper. The result would be closer to AddressSanitizer than full Miri: merged access tracing can catch some invalid accesses to Miri-managed memory, while following native allocations and frees additionally requires the experimental allocation work.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;h3 id=&quot;what-unsound-means-here&quot;&gt;What “unsound” means here&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-unsound-means-here&quot; aria-label=&quot;Anchor link for: what-unsound-means-here&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Also, Miri is now unsound. You’re all very welcome.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--artifact&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Review archaeology&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;please don’t&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;figure class=&quot;margin-artifact&quot;&gt;
  &lt;img src=&quot;&#x2F;images&#x2F;ralf-review-sticker.png&quot; alt=&quot;Cropped Discord message from Ralf Jung reading ‘I think’ and ‘Please don’t.’&quot; width=&quot;190&quot; height=&quot;135&quot;&gt;
  &lt;figcaption&gt;The Rust Community Discord turned some of Ralf’s review feedback into a sticker. I may have provided light encouragement.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;That joke has a less precise scope than one might hope. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;blob&#x2F;15e1f274ca9cdeba049d138487ef849a957b4718&#x2F;README.md#L464-L484&quot;&gt;Miri’s own documentation&lt;&#x2F;a&gt; calls native-library mode unsound because Miri can lose initialization and provenance information for memory shared with native code. The feature is experimental and opt-in. While great care was taken to not make Miri itself literally unsound, one never knows with code like this; it still enables calling arbitrary native binaries from inside Miri itself.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;callbacks-and-threads&quot;&gt;Callbacks and threads&lt;a class=&quot;zola-anchor&quot; href=&quot;#callbacks-and-threads&quot; aria-label=&quot;Anchor link for: callbacks-and-threads&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Callbacks are one of the next targets. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.sourceware.org&#x2F;libffi&#x2F;&quot;&gt;&lt;code&gt;libffi&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which already handles part of the FFI setup, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;libffi&#x2F;libffi&#x2F;blob&#x2F;46cb2e3871059f7f5113329ddcca818de3a8cfae&#x2F;doc&#x2F;libffi.texi#L855-L967&quot;&gt;can create ABI-compatible callback entry points&lt;&#x2F;a&gt;. That solves only the first step. Miri must still regain control, schedule the Rust callback, synchronize memory state, and return to native code.&lt;&#x2F;p&gt;
&lt;p&gt;Native threads pose the same kind of coordination problem and might eventually be parked and resumed through Miri’s scheduler.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--field&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Early users&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;Diesel&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;A Diesel maintainer &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&#x2F;issues&#x2F;4625&quot;&gt;started trying Diesel’s SQLite tests under native-library mode&lt;&#x2F;a&gt;. The immediate roadblock was &lt;code&gt;sqlite3_exec&lt;&#x2F;code&gt;, which requires a callback function pointer to cross the FFI boundary. Miri does not support that yet.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;There is a future in which you pass an arbitrary function pointer into FFI, have it called simultaneously from eighteen threads, and Miri still detects at least a bunch of UB.&lt;&#x2F;p&gt;
&lt;p&gt;That is the point of this story: here is a ridiculous thing, and here is how I willed it into existence despite reality insisting it was a load of crap.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;a class=&quot;zola-anchor&quot; href=&quot;#credits&quot; aria-label=&quot;Anchor link for: credits&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Ralf and Oli survived many painful review iterations while I learned what I was doing. Strophox created Miri’s previous FFI implementation, and ixi built the yaxpeax features this work needs.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks as well to the Capstone developers and all my dependencies. I began with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;icedland&#x2F;iced&quot;&gt;Iced&lt;&#x2F;a&gt;, which was x86-only and also very nice.&lt;&#x2F;p&gt;
&lt;details class=&quot;margin-note margin-note--interlude&quot;&gt;
  
  &lt;summary class=&quot;margin-note__summary&quot;&gt;&lt;span class=&quot;margin-note__label&quot;&gt;Personal effects&lt;span class=&quot;typographic-separator margin-note__separator&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;span&gt;gossip, caffeine, grudges&lt;&#x2F;span&gt;&lt;&#x2F;summary&gt;
  &lt;div class=&quot;margin-note__panel&quot;&gt;
    &lt;p&gt;This project is part of why I now work on Rust. It also made me the subject of some internal gossip; I have heard variants of “Oh God, Ralf told me about this terrifying code you wrote” from several people.&lt;&#x2F;p&gt;
&lt;p&gt;This was my first major Rust contribution and only my second or third large Rust project. The early code—especially the custom allocation setup for mapped memory—was awful. My deepest apologies to everyone helping me review it.&lt;&#x2F;p&gt;
&lt;p&gt;Thank you also to caffeine, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bsky.app&#x2F;profile&#x2F;im.fckn.gay&#x2F;post&#x2F;3mrl3c3yusc2s&quot;&gt;Monster Energy&lt;&#x2F;a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bsky.app&#x2F;profile&#x2F;im.fckn.gay&quot;&gt;my beautiful wife&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There are discredits too. A good programmer needs a grudge—a big grudge. Mine are x86 calling conventions, whoever made &lt;code&gt;ptrace&lt;&#x2F;code&gt; this hard, and AArch64 scalable vector instructions. To hell with all of them, and I owe none of my success &amp;amp; many of my failures to them.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
&lt;&#x2F;details&gt;
&lt;div class=&quot;ornament&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;❦&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;

</content>
        
    </entry>
</feed>
