<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://frida.re/feed.xml" rel="self" type="application/atom+xml" /><link href="https://frida.re/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-10-04T11:41:49+02:00</updated><id>https://frida.re/feed.xml</id><title type="html">Frida • A world-class dynamic instrumentation toolkit</title><subtitle>Observe and reprogram running programs on Windows, macOS, GNU/Linux, iOS, watchOS, tvOS, Android, FreeBSD, and QNX</subtitle><entry><title type="html">Frida 17.22.1 Released</title><link href="https://frida.re/news/2026/10/04/frida-17-22-1-released/" rel="alternate" type="text/html" title="Frida 17.22.1 Released" /><published>2026-10-04T11:35:42+02:00</published><updated>2026-10-04T11:35:42+02:00</updated><id>https://frida.re/news/2026/10/04/frida-17-22-1-released</id><content type="html" xml:base="https://frida.re/news/2026/10/04/frida-17-22-1-released/">&lt;p&gt;A bugfix release, with &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt; behind most of the fixes, and a new
contributor making the C++ bindings a bit more complete.&lt;/p&gt;

&lt;h2 id=&quot;memory-scans-finding-themselves&quot;&gt;Memory scans finding themselves&lt;/h2&gt;

&lt;p&gt;Håvard noticed that a pointer scan on Linux could find the very values it
was looking for, in a stack that no thread was using anymore. The workers of
a scan spill their search values onto their stacks, and once the pool was
freed and its extra workers had exited, glibc kept their stacks around for
reuse, with everything above the exiting frame still mapped and readable.
After our deferred cleanup had uncloaked them, the next scan happily found
its own leftovers. The same goes for anything that ran on the script
scheduler’s thread pool.&lt;/p&gt;

&lt;p&gt;The fix is to discard what a Gum thread spilled on its stack right as it
exits, from the finalize callback that frida-glib runs on the thread itself,
before the thread library gets to cache the stack. Other libcs unmap exited
stacks outright, so only glibc pays for the extra syscall.&lt;/p&gt;

&lt;h2 id=&quot;other-fixes&quot;&gt;Other fixes&lt;/h2&gt;

&lt;p&gt;Håvard also fixed two more Linux-related issues. Instrumenting a function
again while its last listener’s detach was still pending, which is what
GumJS does within its script-wide transaction, could resolve a stale redirect
into a trampoline that was then freed along with the old context. The
function is now treated as still instrumented, reusing its context when both
old and new instrumentation are of the default type, and otherwise
deactivating it on the spot. And &lt;em&gt;dlsym()&lt;/em&gt; no longer crashes on modules that
were pulled in as dependencies by &lt;em&gt;dlopen()&lt;/em&gt;, where glibc has yet to compute
a local scope for the link map we used as the handle.&lt;/p&gt;

&lt;p&gt;Last but not least, &lt;a href=&quot;https://github.com/mnalmahmud&quot;&gt;@mnalmahmud&lt;/a&gt; made it possible to attach probes to
arbitrary instructions from the C++ bindings, through a new &lt;em&gt;ProbeListener&lt;/em&gt;
interface, so that no longer requires dropping down to the C API.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;h3 id=&quot;changelog&quot;&gt;Changelog&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;glibc: Discard dead Gum thread stacks on exit, so memory scans no longer
find leftovers from the scan workers or the script scheduler’s pool.
Thanks for tracking this one down, &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;interceptor: Fix re-attach during a pending detach, which could resolve a
stale redirect into a trampoline that was then freed. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;linux: Fix &lt;em&gt;dlsym()&lt;/em&gt; crash on modules discovered as dependencies of a
&lt;em&gt;dlopen()&lt;/em&gt;, by creating the handle on demand with &lt;em&gt;RTLD_NOLOAD&lt;/em&gt;. Thanks
&lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;gumpp: Add probe listener support, exposing &lt;em&gt;gum_make_probe_listener()&lt;/em&gt; as
a &lt;em&gt;ProbeListener&lt;/em&gt; interface accepted by &lt;em&gt;Interceptor::attach()&lt;/em&gt; and
&lt;em&gt;detach()&lt;/em&gt;. Thanks &lt;a href=&quot;https://github.com/mnalmahmud&quot;&gt;@mnalmahmud&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;frida-compile: Create the output file’s directory as needed, both in
frida-tools and in the npm package. Thanks &lt;a href=&quot;https://github.com/fourcels&quot;&gt;@fourcels&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.22.0 Released</title><link href="https://frida.re/news/2026/10/03/frida-17-22-0-released/" rel="alternate" type="text/html" title="Frida 17.22.0 Released" /><published>2026-10-03T07:56:25+02:00</published><updated>2026-10-03T07:56:25+02:00</updated><id>https://frida.re/news/2026/10/03/frida-17-22-0-released</id><content type="html" xml:base="https://frida.re/news/2026/10/03/frida-17-22-0-released/">&lt;p&gt;Yesterday’s two releases made patterns a first-class citizen for agents and
for tools. This one is about sharing them: frida-compile can now build a
library, so a package on npm can ship its patterns alongside its TypeScript,
and anyone can import it. We also have &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt; to thank for the Swift
ApiResolver now working on Linux, with Windows support landing right behind
it.&lt;/p&gt;

&lt;h2 id=&quot;libraries&quot;&gt;Libraries&lt;/h2&gt;

&lt;p&gt;Say you’ve written a few patterns and some helpers around them, and want to
publish them for other agents to use. Up until now that meant running
frida-compile once to get the pattern typings, then &lt;em&gt;tsc&lt;/em&gt; to emit the package,
with a &lt;em&gt;tsconfig.json&lt;/em&gt; carefully matched to how Frida.Compiler resolves
imports. Two compilers over the same sources is one too many.&lt;/p&gt;

&lt;p&gt;With &lt;em&gt;frida-compile –library&lt;/em&gt;, Frida.Compiler does the whole job. Here’s
&lt;em&gt;lib/index.ts&lt;/em&gt; in a package that finds players in a game:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./patterns/player.hexpat&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findPlayers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RangeDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;scanSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`health=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; lives=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; at (&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next to it sits &lt;em&gt;lib/patterns/player.hexpat&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#pragma abi native
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Vec3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vec3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And that’s all the source there is. The &lt;em&gt;package.json&lt;/em&gt; needs no &lt;em&gt;typescript&lt;/em&gt;,
no &lt;em&gt;@types/frida-gum&lt;/em&gt;, and no &lt;em&gt;tsconfig.json&lt;/em&gt;, only &lt;a href=&quot;https://www.npmjs.com/package/frida-compile&quot;&gt;frida-compile&lt;/a&gt; from npm:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;frida-module-example&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./dist/index.js&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;types&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./dist/index.d.ts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;files&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/dist&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;prepare&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;frida-compile --library lib/index.ts -o dist&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;frida-compile&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^19.1.0&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Running that build gives us:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;frida-compile &lt;span class=&quot;nt&quot;&gt;--library&lt;/span&gt; lib/index.ts &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; dist
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find dist &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f | &lt;span class=&quot;nb&quot;&gt;sort
&lt;/span&gt;dist/index.d.ts
dist/index.js
dist/index.js.map
dist/patterns/player.hexpat
dist/patterns/player.hexpat.d.ts&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;One module and one declaration file per source, with the patterns copied
alongside and their generated typings next to them. The declarations are
exactly what you’d hope for:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./patterns/player.hexpat&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findPlayers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RangeDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that the pattern is shipped as source, and not as the JavaScript that
Frida.Compiler turns it into. That’s deliberate: the generated code leans on a
runtime that the consumer’s build provides and dedupes across packages, the
pattern can be imported by other patterns and by tools such as Luma, and the
pattern language is a far more stable interface than our emitted code. The
consumer’s Frida.Compiler compiles it as part of their build, in milliseconds,
and caches the result.&lt;/p&gt;

&lt;p&gt;Which brings us to the consumer. After &lt;em&gt;npm install frida-module-example&lt;/em&gt;,
an agent can use both the helpers and the pattern itself:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;findPlayers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;frida-module-example&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;frida-module-example/dist/patterns/player.hexpat&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arena&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findPlayers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arena&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;as &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RangeDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;frida &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; agent.ts
&lt;span class=&quot;nv&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;100 &lt;span class=&quot;nv&quot;&gt;lives&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3 at &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0, 0, 1.5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A few more details:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;-w&lt;/em&gt; keeps the library fresh as you edit, which pairs nicely with
&lt;em&gt;npm link&lt;/em&gt; while iterating on a package together with an app.&lt;/li&gt;
  &lt;li&gt;Source maps are emitted next to each module, with the sources inlined, so
consumers get real stack traces without you shipping &lt;em&gt;lib/&lt;/em&gt;. Pass &lt;em&gt;-S&lt;/em&gt; to
leave them out.&lt;/li&gt;
  &lt;li&gt;Errors are reported just like for agents, with paths relative to the
project, and nothing is written when there are any:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;lib/broken.ts:1:14 - error TS2322: Type &lt;span class=&quot;s1&quot;&gt;&apos;string&apos;&lt;/span&gt; is not assignable to &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;number&apos;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
compilation failed&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;The output mirrors your source tree under its common directory, so
&lt;em&gt;lib/index.ts&lt;/em&gt; lands at &lt;em&gt;dist/index.js&lt;/em&gt;. If your &lt;em&gt;tsconfig.json&lt;/em&gt; sets
&lt;em&gt;rootDir&lt;/em&gt;, that’s honored instead.&lt;/li&gt;
  &lt;li&gt;This is &lt;em&gt;Compiler.build_library()&lt;/em&gt; and &lt;em&gt;Compiler.watch_library()&lt;/em&gt; in
frida-core, so it’s available from all of our language bindings, and
frida-compile exposes it both in frida-tools and in the npm package.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;swift&quot;&gt;Swift&lt;/h2&gt;

&lt;p&gt;The Swift ApiResolver, which learned to find types, protocols and
conformances yesterday, was until now only functional on Apple platforms. It
looked for &lt;em&gt;libswiftCore.dylib&lt;/em&gt;, borrowed &lt;em&gt;free()&lt;/em&gt; from &lt;em&gt;libsystem_malloc&lt;/em&gt;,
and matched metadata sections by their Mach-O names, so on Linux every query
failed with “unsupported Swift runtime”.&lt;/p&gt;

&lt;p&gt;Håvard fixed all of that: the resolver now names the Swift core library and
the metadata sections per platform, takes &lt;em&gt;free()&lt;/em&gt; from the C runtime where
there is no &lt;em&gt;libsystem_malloc&lt;/em&gt;, and keeps its demangler per instance, as on
Linux a &lt;em&gt;dlclose()&lt;/em&gt; unmaps &lt;em&gt;libswiftCore&lt;/em&gt; and a cached pointer could outlive
it. He also made our Swift tests actually run on Linux CI, where they had
been silently skipping all along, and report skips as skips rather than as
passes. Thanks a lot, Håvard!&lt;/p&gt;

&lt;p&gt;With that groundwork in place, Windows was a small step: &lt;em&gt;swiftCore.dll&lt;/em&gt;, the
&lt;em&gt;.sw5*&lt;/em&gt; sections, and freeing demangled names through the UCRT. One Windows
quirk worth knowing is that &lt;em&gt;swiftrt.obj&lt;/em&gt; brackets each metadata section with
zeroed start and stop markers, which the resolver now skips. So wherever a
Swift runtime is loaded, &lt;em&gt;new ApiResolver(‘swift’)&lt;/em&gt; and its &lt;em&gt;functions:&lt;/em&gt;,
&lt;em&gt;types:&lt;/em&gt;, &lt;em&gt;protocols:&lt;/em&gt; and &lt;em&gt;conformances:&lt;/em&gt; queries now work the same.&lt;/p&gt;

&lt;h2 id=&quot;eof&quot;&gt;EOF&lt;/h2&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;h3 id=&quot;changelog&quot;&gt;Changelog&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;compiler: Add library builds, through &lt;em&gt;Compiler.build_library()&lt;/em&gt; and
&lt;em&gt;Compiler.watch_library()&lt;/em&gt;, exposed as &lt;em&gt;frida-compile –library&lt;/em&gt;. (Covered
above.)&lt;/li&gt;
  &lt;li&gt;swift-api-resolver: Add Linux support, naming the Swift core library and
metadata sections per platform, and keeping the demangler per resolver
instance. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;swift-api-resolver: Add Windows support, including skipping the zeroed
section markers that &lt;em&gt;swiftrt.obj&lt;/em&gt; emits.&lt;/li&gt;
  &lt;li&gt;swift-api-resolver: Find the Swift toolchain in tests, so they run on
GitHub’s Ubuntu runners instead of silently skipping. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;gumjs: Handle every arm64 vector arrangement when parsing instruction
operands. Single-lane and narrow arrangements such as &lt;em&gt;v0.b[0]&lt;/em&gt; reached an
unreachable default, which crashed the process once assertions were compiled
out. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;windows: Fix section names and sizes. Names of exactly eight characters lack
a NUL terminator, and sizes are now the virtual size rather than the
file-aligned raw size, as the loader sees them.&lt;/li&gt;
  &lt;li&gt;swift: Regenerate the bindings for library builds.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.21.0 Released</title><link href="https://frida.re/news/2026/10/02/frida-17-21-0-released/" rel="alternate" type="text/html" title="Frida 17.21.0 Released" /><published>2026-10-02T20:28:35+02:00</published><updated>2026-10-02T20:28:35+02:00</updated><id>https://frida.re/news/2026/10/02/frida-17-21-0-released</id><content type="html" xml:base="https://frida.re/news/2026/10/02/frida-17-21-0-released/">&lt;p&gt;Two releases in one day? Software is hard, and APIs are harder. But this one
is worth it: &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt; has taught the Swift ApiResolver to find types,
protocols and protocol conformances, and the new PatternCompiler API has been
reshaped to work on files, so patterns can import each other on the host side
as well.&lt;/p&gt;

&lt;h2 id=&quot;swift&quot;&gt;Swift&lt;/h2&gt;

&lt;p&gt;Frida’s &lt;em&gt;ApiResolver(‘swift’)&lt;/em&gt; has been around for a while, letting you find
Swift functions by their demangled names, with globs. Behind the scenes it
walks the Swift metadata that the compiler emits into every Swift binary, which
is also where the information about types and protocols lives. Håvard has been
hacking on this resolver since 2023, and in 17.20.0 he made it work in a lot
more processes by demangling through libswiftCore, which is always present when
Swift code is running, instead of libswiftDemangle, which typically isn’t.&lt;/p&gt;

&lt;p&gt;With that out of the way, this release adds three new kinds of queries. First,
&lt;em&gt;types:&lt;/em&gt; and &lt;em&gt;protocols:&lt;/em&gt; match nominal types and protocols by their full
name, giving you the address of the context descriptor:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resolver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ApiResolver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;swift&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enumerateMatches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;types:*!Swift.Int&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enumerateMatches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;protocols:*!Swift.Hashable&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;/usr/lib/swift/libswiftCore.dylib!Swift.Int 0x19bf8009c
/usr/lib/swift/libswiftCore.dylib!Swift.Hashable 0x19bf7c490&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The part before the &lt;em&gt;!&lt;/em&gt; matches the module, like with the other resolvers, so
&lt;em&gt;types:*libswiftCore*!Swift.Dictionary*&lt;/em&gt; narrows things down to a specific
library, and finds nested types as well:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;/usr/lib/swift/libswiftCore.dylib!Swift.Dictionary 0x19bf7abe8
/usr/lib/swift/libswiftCore.dylib!Swift.Dictionary.Keys 0x19bf7ac54
/usr/lib/swift/libswiftCore.dylib!Swift.Dictionary.Values 0x19bf7ac90
/usr/lib/swift/libswiftCore.dylib!Swift.Dictionary.Keys.Iterator 0x19bf7accc
/usr/lib/swift/libswiftCore.dylib!Swift.Dictionary.Values.Iterator 0x19bf7ad08&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Second, &lt;em&gt;conformances:&lt;/em&gt; matches protocol conformances by type and protocol
name, giving you the address of the conformance descriptor. This is the one
I’m most excited about, as it answers questions like “which protocols does
this type implement?”:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enumerateMatches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;conformances:Swift.Int!Swift.*&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Swift.Int!Swift.Encodable 0x19bf5f6c4
Swift.Int!Swift.Decodable 0x19bf5f6d4
Swift.Int!Swift.CodingKeyRepresentable 0x19bf5f984
Swift.Int!Swift.CustomReflectable 0x19bf612ec
Swift.Int!Swift._CustomPlaygroundQuickLookable 0x19bf612fc
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And the other way around, “which types implement this protocol?”, which is
where it gets interesting in a big app:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;encodable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enumerateMatches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;conformances:*!Swift.Encodable&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;types conform to Encodable&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;encodable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;3735 types conform to Encodable
UIIntelligenceSupport.IntelligenceElement.Axis!Swift.Encodable 0x2a5e0a1c8
UIIntelligenceSupport.IntelligenceElement.Image!Swift.Encodable 0x2a5e0a9d0
UIIntelligenceSupport.IntelligenceElement.CustomAppEntity!Swift.Encodable 0x2a5e0b0e8&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;From the conformance descriptor you can get to the witness table, and from the
context descriptor to the type’s metadata, fields and methods. So these are
the building blocks for anything that wants to understand a Swift program’s
types at runtime, from pretty-printing a value to hooking every type that
implements a certain protocol. Expect to see more built on top of them.&lt;/p&gt;

&lt;p&gt;He also fixed the &lt;em&gt;/i&lt;/em&gt; suffix, which the Swift resolver accepted but didn’t
actually honor. Thanks a lot, Håvard, for all the excellent work on this!&lt;/p&gt;

&lt;h2 id=&quot;patterncompiler&quot;&gt;PatternCompiler&lt;/h2&gt;

&lt;p&gt;This morning’s release introduced the &lt;em&gt;PatternCompiler&lt;/em&gt; API, which compiles a
pattern on the host and decodes memory against it. It took a source string,
which seemed convenient, but meant it had no idea where that source lived, so a
pattern could not import anything but the &lt;em&gt;std&lt;/em&gt; library. That’s fixed now, and
the API mirrors &lt;em&gt;Compiler.build()&lt;/em&gt;: you hand it a path, and optionally a project
root, with the latter inferred from the entrypoint when left out. Say we have
&lt;em&gt;proj/player.hexpat&lt;/em&gt;, importing a &lt;em&gt;Vec3&lt;/em&gt; from &lt;em&gt;proj/common.pat&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#pragma abi native
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;common&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Vec3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Imports resolve exactly like they do when Frida.Compiler builds an agent:
relative to the importing file, then from &lt;em&gt;node_modules&lt;/em&gt;. Each type now tells
you which file it was declared in, and so does each diagnostic, with paths
relative to the project root, the same way build diagnostics are reported:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frida&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frida&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PatternCompiler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;proj/player.hexpat&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diagnostics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; bytes&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With a semicolon missing in &lt;em&gt;common.pat&lt;/em&gt;, that reports:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;proj/common.pat:5:1: expected &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And once fixed:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;proj/common.pat: struct Vec3, 12 bytes
proj/player.hexpat: struct Player, 16 bytes&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The language server got the same treatment, so a &lt;em&gt;.hexpat&lt;/em&gt; that imports an
unsaved buffer in another tab resolves it, and problems stay attributed to the
file they’re in. Our Swift bindings have been regenerated accordingly, and the
other bindings pick this up automatically.&lt;/p&gt;

&lt;p&gt;This is a breaking change to an API that shipped this morning, so hopefully
nobody has built anything on it yet. If you have, the migration is to write
your pattern to a file and pass its path.&lt;/p&gt;

&lt;h2 id=&quot;eof&quot;&gt;EOF&lt;/h2&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;h3 id=&quot;changelog&quot;&gt;Changelog&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;swift-api-resolver: Add &lt;em&gt;types:&lt;/em&gt; and &lt;em&gt;protocols:&lt;/em&gt; queries, matching the
descriptors in &lt;em&gt;__swift5_types&lt;/em&gt;, &lt;em&gt;__swift5_types2&lt;/em&gt; and
&lt;em&gt;__swift5_protos&lt;/em&gt; by full name. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;swift-api-resolver: Add &lt;em&gt;conformances:&lt;/em&gt; queries, matching
&lt;em&gt;__swift5_proto&lt;/em&gt; records by type and protocol name. Also make &lt;em&gt;/i&lt;/em&gt; take
effect. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;compiler: Compile patterns from files, with imports and includes resolving the
way they do in agent builds, and the file of each type and diagnostic named
relative to the project root. (Covered above.)&lt;/li&gt;
  &lt;li&gt;compiler: Fix crash on a relative project root, which took down the whole
process from inside the TypeScript compiler’s virtual filesystem.&lt;/li&gt;
  &lt;li&gt;swift: Regenerate the PatternCompiler bindings.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.20.0 Released</title><link href="https://frida.re/news/2026/10/02/frida-17-20-0-released/" rel="alternate" type="text/html" title="Frida 17.20.0 Released" /><published>2026-10-02T03:11:53+02:00</published><updated>2026-10-02T03:11:53+02:00</updated><id>https://frida.re/news/2026/10/02/frida-17-20-0-released</id><content type="html" xml:base="https://frida.re/news/2026/10/02/frida-17-20-0-released/">&lt;p&gt;For as long as Frida has existed, dealing with structs has been one of its
weak spots. Say you’ve found a &lt;em&gt;Player&lt;/em&gt; struct in a game, and you want to read
its &lt;em&gt;lives&lt;/em&gt; field. What you’d end up writing is something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;readU32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That magic &lt;em&gt;4&lt;/em&gt; is an offset you worked out by hand, &lt;em&gt;readU32()&lt;/em&gt; is a type you
also worked out by hand, and neither is written down anywhere except in that
one line. Multiply that by every field of every struct you care about, and you
end up with scripts that are brittle, hard to read, and where the layout can’t
really be shared with anyone. And if the struct looks different on 32-bit vs.
64-bit, you get to maintain two sets of offsets.&lt;/p&gt;

&lt;p&gt;I’ve been pondering this for years. What I really wanted was a typesafe
approach, where the TypeScript compiler knows which fields exist and what their
types are, so typos get caught at compile time, and the editor can auto-complete
field names. It was kind of a given that this would require a codegen step, and
that always felt like too much friction to put on users.&lt;/p&gt;

&lt;p&gt;But then Frida.Compiler came along. It hasn’t been around since the beginning,
but now that it’s here, powering frida-compile, the REPL, and tools like Luma,
that codegen step can be made entirely invisible. So that’s what this release
is about.&lt;/p&gt;

&lt;h2 id=&quot;patterns&quot;&gt;Patterns&lt;/h2&gt;

&lt;p&gt;Rather than inventing yet another struct description language, we’ve adopted
the &lt;a href=&quot;https://docs.werwolv.net/pattern-language&quot;&gt;pattern language&lt;/a&gt; from &lt;a href=&quot;https://imhex.werwolv.net/&quot;&gt;ImHex&lt;/a&gt;. It’s a C-like language for describing
binary data, originally created for ImHex’s hex editor, with structs, unions,
enums, bitfields, pointers, conditionals, dynamically sized arrays, and a
standard library. There’s an &lt;a href=&quot;https://github.com/WerWolv/ImHex-Patterns&quot;&gt;ImHex-Patterns&lt;/a&gt; repository full of patterns for
common file formats, and the language has since been adopted elsewhere, too:
x64dbg supports it through the &lt;a href=&quot;https://github.com/x64dbg/DataExplorer&quot;&gt;DataExplorer&lt;/a&gt; plugin, and radare2 through
&lt;a href=&quot;https://github.com/radareorg/r2hexpat&quot;&gt;r2hexpat&lt;/a&gt;. So chances are you’ll find existing patterns you can reuse, and
the patterns you write for Frida are useful in those tools as well.&lt;/p&gt;

&lt;p&gt;Frida 17.20.0 implements this language in Frida.Compiler, in Go, right next to
the TypeScript compiler. Let’s take it for a spin. Here’s &lt;em&gt;game.hexpat&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#pragma abi native
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Role&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Vec3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vec3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Warrior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Mage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Rogue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you’ve written a C struct you already know how to read this. The one thing
that stands out is &lt;em&gt;#pragma abi native&lt;/em&gt;, which we’ll get back to in a moment.&lt;/p&gt;

&lt;p&gt;From &lt;em&gt;agent.ts&lt;/em&gt; we then import the pattern as if it were any other module:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Role&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./game.hexpat&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;roster&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;roster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Mage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;roster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Warrior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;carol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;roster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;carol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;health&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;carol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;carol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Rogue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;carol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Player.size:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;alice.next.next.role:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In a real-world scenario the game would obviously own these structs, and we’d
have found them through Interceptor, memory scanning, or similar. But to keep
the example self-contained we allocate three of them ourselves.&lt;/p&gt;

&lt;p&gt;Let’s run it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;frida &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; agent.ts
Compiling agent.ts...
Compiled agent.ts &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;20 ms&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Player.size: 32
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;health&quot;&lt;/span&gt;: 100,
  &lt;span class=&quot;s2&quot;&gt;&quot;lives&quot;&lt;/span&gt;: 3,
  &lt;span class=&quot;s2&quot;&gt;&quot;role&quot;&lt;/span&gt;: 1,
  &lt;span class=&quot;s2&quot;&gt;&quot;position&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;x&quot;&lt;/span&gt;: 1.5,
    &lt;span class=&quot;s2&quot;&gt;&quot;y&quot;&lt;/span&gt;: &lt;span class=&quot;nt&quot;&gt;-2&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;: 3
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;next&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;0x140cb5bc0&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
alice.next.next.role: Rogue&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A few things to note here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Each struct becomes a class. &lt;em&gt;Player.at(address)&lt;/em&gt; gives you a live view of
the memory at that address, where each property reads or writes the
underlying memory directly. Nothing is copied, so what you see is always
what’s in memory right now.&lt;/li&gt;
  &lt;li&gt;Nested structs like &lt;em&gt;position&lt;/em&gt; are views too, and pointer fields like &lt;em&gt;next&lt;/em&gt;
give you a view of the pointee, or &lt;em&gt;null&lt;/em&gt;. Assigning to a pointer field
accepts either a view or a NativePointer.&lt;/li&gt;
  &lt;li&gt;Enums become objects with a reverse mapping, so &lt;em&gt;Role[alice.role]&lt;/em&gt; gives you
&lt;em&gt;“Mage”&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Player.size&lt;/em&gt; is the struct’s size in bytes, and &lt;em&gt;JSON.stringify()&lt;/em&gt; just
works.&lt;/li&gt;
  &lt;li&gt;Nothing was compiled ahead of time. The REPL handed &lt;em&gt;agent.ts&lt;/em&gt; to
Frida.Compiler, which spotted the &lt;em&gt;.hexpat&lt;/em&gt; import, compiled the pattern to
JavaScript, and bundled it with the agent. The same happens if you run
&lt;em&gt;frida-compile agent.ts -o _agent.js&lt;/em&gt;, where the resulting bundle is
self-contained and can be loaded by any of our bindings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;native-layout&quot;&gt;Native layout&lt;/h3&gt;

&lt;p&gt;Since the pattern language was designed for file formats, ImHex lays out
structs packed, with no padding between fields, as that is what file formats
usually look like. Frida on the other hand needs to deal with in-memory structs
as well, as laid out by a C compiler, and those are padded to natural
alignment. That’s where &lt;em&gt;#pragma abi native&lt;/em&gt; comes in. It only exists in Frida’s
dialect of the language, and tells the compiler to lay out structs the way the
target’s C compiler would. In the example above, &lt;em&gt;role&lt;/em&gt; is a single byte,
followed by three bytes of padding so that &lt;em&gt;position&lt;/em&gt; ends up 4-byte aligned,
and &lt;em&gt;next&lt;/em&gt; ends up 8-byte aligned on a 64-bit process. Hence &lt;em&gt;Player.size&lt;/em&gt;
being 32 rather than 25. Leave the pragma out and you get ImHex’s packed
layout, which is what you want when decoding a file format that happens to be
mapped into memory.&lt;/p&gt;

&lt;p&gt;The generated JavaScript also takes the target’s ABI into account. Pointer
fields such as &lt;em&gt;next&lt;/em&gt; are 8 bytes on a 64-bit process and 4 bytes on a 32-bit
one, which shifts the offsets of everything after them, and the alignment rules
differ between e.g. 32-bit Windows and 32-bit Linux. Frida.Compiler computes
the layouts for all of these at compile time, and the generated code picks the
right one at runtime based on the process it ends up in. So a single compiled
agent supports any target Frida supports, with no per-architecture offsets to
maintain.&lt;/p&gt;

&lt;h3 id=&quot;type-safety&quot;&gt;Type-safety&lt;/h3&gt;

&lt;p&gt;This is the part that I’m most excited about. When Frida.Compiler loads a
&lt;em&gt;.hexpat&lt;/em&gt;, it also generates TypeScript declarations for it, written next to
the pattern as &lt;em&gt;game.hexpat.d.ts&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NativePointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NativePointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NativePointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Parsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NativePointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;lives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Vec3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NativePointer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;toJSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This means the TypeScript compiler knows exactly which fields are available and
what their types are. Misspell a field and you get a compile error. Your editor
auto-completes field names. Add a &lt;em&gt;char name[16]&lt;/em&gt; to the struct and it shows up
as a read-only &lt;em&gt;string&lt;/em&gt;, and the compiler will tell you if you try to assign to
it. (As it told me while writing this post.) Mistakes in the pattern itself are
reported with file and line, just like TypeScript errors:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;frida-compile agent.ts &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; _agent.js
game.hexpat:5:5 - error TS-1: unknown &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;Badge
compilation failed&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You may want to add &lt;em&gt;*.hexpat.d.ts&lt;/em&gt; to your &lt;em&gt;.gitignore&lt;/em&gt;, as these get
regenerated on every build.&lt;/p&gt;

&lt;h3 id=&quot;scanning&quot;&gt;Scanning&lt;/h3&gt;

&lt;p&gt;Now for the part that makes this feel like magic. Say we’re looking for a
Player with full health and three lives, but we have no idea where in memory
it might be. Each generated class has a static &lt;em&gt;pattern()&lt;/em&gt; method that takes a
subset of the fields and produces a match pattern for &lt;em&gt;Memory.scan()&lt;/em&gt;, with the
fields you leave out wildcarded:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;pattern:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;scanSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;roster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; with &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lives&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; lives`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Which gives us:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;pattern: 64 00 00 00 03 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
0x140cb5ba0: Mage with 3 lives
0x140cb5be0: Rogue with 3 lives&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Endianness, field offsets, padding: all taken care of. In a real game you’d
scan the heap ranges from &lt;em&gt;Process.enumerateRanges(‘rw-‘)&lt;/em&gt; instead of our
little roster, and perhaps throw in an enum value or a nested field to narrow
things down, e.g. &lt;em&gt;Player.pattern({ role: Role.Rogue, position: { z: 3 } })&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;beyond-the-view&quot;&gt;Beyond the view&lt;/h3&gt;

&lt;p&gt;The live view covers structs that are plain data, which is most of what you’ll
run into inside a process. But the pattern language can do a lot more: arrays
sized by earlier fields, conditionals, pointers with custom bases, locals,
functions, attributes like &lt;em&gt;[[format]]&lt;/em&gt; and &lt;em&gt;[[color]]&lt;/em&gt;, the &lt;em&gt;std&lt;/em&gt; library, and
so on. For those there’s &lt;em&gt;parse()&lt;/em&gt;, which decodes a snapshot of the memory with
the full ImHex semantics. Let’s try it on something every process on macOS
and iOS has: the Mach-O header of its main executable. We’ll put this in
&lt;em&gt;macho.hexpat&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#pragma endian little
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MachO&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;MachHeader&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LoadCommand&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ncmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MachHeader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;FF8800&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;CpuType&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cputype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cpusubtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ncmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sizeofcmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LoadCommand&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cmdsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmdsize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sealed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CpuType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;X86_64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x01000007&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ARM64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0100000C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Execute&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Dylib&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;MachO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macho&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note the lack of &lt;em&gt;#pragma abi native&lt;/em&gt; here, as this is a file format. Also
note the placement at the end, which is how ImHex patterns typically declare
what’s at the start of the file. In our case the “file” is a chunk of memory,
and a pattern with placements gives us a &lt;em&gt;parse()&lt;/em&gt; export that decodes them:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ts&quot; data-lang=&quot;ts&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MachHeader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CpuType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FileType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./macho.hexpat&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mainModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MachHeader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;magic:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CpuType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cputype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;FileType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ncmds:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ncmds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;macho&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;commands:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`  cmd=0x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; cmdsize=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cmdsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;`@ &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;frida &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; macho.ts
Compiling macho.ts...
Compiled macho.ts &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;19 ms&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
magic: feedfacf ARM64 Execute
ncmds: 20
commands: 20
  &lt;span class=&quot;nv&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0x19 &lt;span class=&quot;nv&quot;&gt;cmdsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;72 @ 0x102a64020
  &lt;span class=&quot;nv&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0x19 &lt;span class=&quot;nv&quot;&gt;cmdsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;312 @ 0x102a64068
  &lt;span class=&quot;nv&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0x19 &lt;span class=&quot;nv&quot;&gt;cmdsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;152 @ 0x102a641a0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The second argument to &lt;em&gt;parse()&lt;/em&gt; bounds how much memory it may read, which is a
good idea when a pattern’s arrays are sized by data you don’t fully trust yet.
The result is a tree of plain values, with &lt;em&gt;$address&lt;/em&gt; and &lt;em&gt;$size&lt;/em&gt; on each
struct, so you know where every piece came from. And &lt;em&gt;MachHeader.at()&lt;/em&gt; still
works alongside it, as a live view, since that struct is plain data.&lt;/p&gt;

&lt;p&gt;Patterns can import other patterns, with imports resolved relative to the
importing file, and then from &lt;em&gt;node_modules&lt;/em&gt;, so patterns can be published as
npm packages. The &lt;em&gt;std&lt;/em&gt; library is built in, so &lt;em&gt;import std.mem;&lt;/em&gt; just works.
We run the ImHex-Patterns corpus as part of our test-suite, and 303 of its 312
patterns compile as-is, with the rest depending on ImHex itself, or failing
there too. Visualizers, i.e. &lt;em&gt;hex::visualize()&lt;/em&gt;, are evaluated by the host-side
API covered next, and ignored inside agents.&lt;/p&gt;

&lt;h2 id=&quot;patterncompiler&quot;&gt;PatternCompiler&lt;/h2&gt;

&lt;p&gt;Frida.Compiler takes care of agents, but tools built on top of Frida often want
to decode memory on the host side, without injecting any pattern code into the
target. For that there’s a new &lt;em&gt;PatternCompiler&lt;/em&gt; API in frida-core, which the
auto-generated bindings, i.e. frida-python, frida-node and frida-swift, pick up
automatically. You hand it a pattern source, and it hands you a
&lt;em&gt;PatternModule&lt;/em&gt; that describes the types the pattern declares, and that can
decode a chunk of bytes against any of them. Let’s use it from Python to decode
the same Mach-O header we looked at above:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pathlib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frida&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frida&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;attach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create_script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
rpc.exports = {
  mainModule() {
    const { base, name } = Process.mainModule;
    return [name, base.toString()];
  },
  read(address, size) {
    return ptr(address).readByteArray(size);
  },
};
&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exports_sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;main_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exports_sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frida&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PatternCompiler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;macho.hexpat&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                                         &lt;span class=&quot;n&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;darwin&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;arm64&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diagnostics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;macho&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;MachO&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macho&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; @ &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;macho&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#x&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
          &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;!s:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;macho&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; load commands, &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; bytes&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python3 decode.py
Python @ 0x104ec0000
  magic       le u32     4277009103 FF8800
  cputype     CpuType    ARM64
  cpusubtype  le u32     0
  filetype    FileType   Execute
  ncmds       le u32     20
  sizeofcmds  le u32     1232
  flags       le u32     2097285
  reserved    le u32     0
  commands: 20 load commands, 1232 bytes&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The decoded tree carries everything a UI needs: the address, offset and size of
each value, enum labels, &lt;em&gt;[[format]]&lt;/em&gt; output, &lt;em&gt;[[comment]]&lt;/em&gt;, &lt;em&gt;[[color]]&lt;/em&gt;, and
any visualizer the pattern attached to it, along with the visualizer’s evaluated
arguments. Rendering is up to the tool. The module also describes the declared
types, with their fields, offsets and sizes, so you can build a type browser
without decoding anything. Patterns may declare &lt;em&gt;in&lt;/em&gt; variables, which you
supply by name when decoding, and if a pattern attaches a &lt;em&gt;button&lt;/em&gt; visualizer,
&lt;em&gt;call_function()&lt;/em&gt; lets you press it. Compile errors don’t throw. They end up in
&lt;em&gt;diagnostics&lt;/em&gt;, with line and column, so they can be shown in an editor.&lt;/p&gt;

&lt;p&gt;Speaking of editors: the &lt;em&gt;Frida.LanguageServer&lt;/em&gt; API introduced in 17.18.0 now
serves &lt;em&gt;.hexpat&lt;/em&gt; and &lt;em&gt;.pat&lt;/em&gt; documents as well, with diagnostics, completion,
hover, document symbols, folding ranges, semantic tokens, go-to-definition, and
color swatches for &lt;em&gt;[[color]]&lt;/em&gt; attributes. Completion knows about the &lt;em&gt;std&lt;/em&gt;
library and the visualizer names. And when you’re writing a TypeScript agent
that imports a pattern, completion of its fields comes for free through the
generated declarations.&lt;/p&gt;

&lt;h2 id=&quot;luma&quot;&gt;Luma&lt;/h2&gt;

&lt;p&gt;All of this is already put to use in &lt;a href=&quot;https://luma.frida.re/&quot;&gt;Luma&lt;/a&gt;, the official Frida GUI, as of
its upcoming release. Luma gains a &lt;em&gt;Patterns&lt;/em&gt; section in the sidebar, where
patterns and shared libraries live, with an editor backed by the language
server:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/luma-pattern-editor.png&quot; alt=&quot;luma-pattern-editor&quot; title=&quot;Luma&apos;s pattern editor&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each file expands to show the types it declares, so you can jump straight to a
struct. Hex views, whether from a memory insight or a REPL hexdump, get a
“Decode at … as…” context menu, listing the types from your pattern library.
Pick one and the bytes light up with a colored outline per field, with a tree
next to it showing names, types and values. Clicking a byte selects the field
it belongs to, and selecting a field scrolls the hex view to it. Here’s a Mach-O
header decoded straight out of a running process:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/luma-pattern-macho.png&quot; alt=&quot;luma-pattern-macho&quot; title=&quot;Mach-O decoded in Luma&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The visualizers are where it gets really fun. The pattern language lets you
attach a visualizer to a field, such as an image, a line plot, a 3D model,
coordinates on a map, audio samples, a timestamp, a bitfield as a digital
signal, or a disassembly, and Luma renders them:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/luma-pattern-image.png&quot; alt=&quot;luma-pattern-image&quot; title=&quot;An embedded PNG&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/luma-pattern-line-plot.png&quot; alt=&quot;luma-pattern-line-plot&quot; title=&quot;A float array as a line plot&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/luma-pattern-map.png&quot; alt=&quot;luma-pattern-map&quot; title=&quot;Coordinates on a map&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/luma-pattern-3d.png&quot; alt=&quot;luma-pattern-3d&quot; title=&quot;Vertices and indices as a 3D model&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/luma-pattern-disassembler.png&quot; alt=&quot;luma-pattern-disassembler&quot; title=&quot;Bytes as code&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And because Luma’s REPL, custom instruments and tracer hooks are all compiled
through Frida.Compiler, they get the same treatment as the agent we wrote
above: import a pattern, and you get live views, &lt;em&gt;pattern()&lt;/em&gt; for scanning,
&lt;em&gt;parse()&lt;/em&gt; for the full language, and completion of the fields while typing.&lt;/p&gt;

&lt;h2 id=&quot;eof&quot;&gt;EOF&lt;/h2&gt;

&lt;p&gt;There’s also a bunch of other changes in this release, so definitely check out
the changelog below.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;h3 id=&quot;changelog&quot;&gt;Changelog&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;compiler: Add ImHex pattern language support. (Covered extensively above.)&lt;/li&gt;
  &lt;li&gt;gumjs: Let NativePointer reads and writes take an optional offset, e.g.
&lt;em&gt;p.readU32(4)&lt;/em&gt;, so a field can be accessed without allocating a NativePointer
for its address. This is also what the generated pattern views use under the
hood.&lt;/li&gt;
  &lt;li&gt;gumjs: Return the pointer from &lt;em&gt;writeVolatile()&lt;/em&gt;, for consistency with the
other writers.&lt;/li&gt;
  &lt;li&gt;api-resolver: Descend the Darwin export trie when an exports query is a
literal prefix followed by a trailing wildcard, such as
&lt;em&gt;exports:*!pthread_*&lt;/em&gt;, instead of enumerating every export of every
matching module. With 676 modules loaded, 243 such queries went from 35 s to
65 ms. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;swift-api-resolver: Demangle using &lt;em&gt;swift_demangle()&lt;/em&gt; from libswiftCore,
which is always present in Swift processes, instead of libswiftDemangle,
which typically isn’t loaded. Also resolve it lazily, so the resolver starts
working once libswiftCore gets loaded. Thanks &lt;a href=&quot;https://twitter.com/hsorbo&quot;&gt;@hsorbo&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;arm64: Bound the relocator’s reachability scan. Its 1024-byte budget was
reset for each block, so the scan would follow branch targets without limit,
which on Android made hooking branchy code cost hundreds of milliseconds per
target.&lt;/li&gt;
  &lt;li&gt;exceptor: Stop saving the signal mask on each try, which cost a syscall per
attempt and wasn’t needed.&lt;/li&gt;
  &lt;li&gt;payload: Fix Android agents crashing on load, caused by the module registry
reading &lt;em&gt;/proc/self/auxv&lt;/em&gt; before the libc shim had set up its stdio
registries.&lt;/li&gt;
  &lt;li&gt;barebone: Make the macOS Android emulator a first-class target. The shim has
been rewritten as a CModule so the hot path runs lock-free, all cores are
resumed, registers are pushed straight to the vcpu, trapped debug-register
accesses are handled instead of aborting the VM, and idle scheduler hits are
filtered natively. Apps can also be enumerated and spawned.&lt;/li&gt;
  &lt;li&gt;barebone: Inject the agent into SMP arm64 Linux, report thread state and
registers on Linux, name Linux processes by their cmdline, and keep the arm64
copy off huge pages.&lt;/li&gt;
  &lt;li&gt;linux-kernel-image: Mine kallsyms from 32-bit kernels and arm64 kernels with
VA_BITS=48, including Rust symbol names longer than 80 characters.&lt;/li&gt;
  &lt;li&gt;barebone: Fix the build without the Droidy backend, and the 32-bit Arm build.&lt;/li&gt;
  &lt;li&gt;base: Keep Posix types out of the API, so consumers of frida-base no longer
need posix.vapi.&lt;/li&gt;
  &lt;li&gt;compiler: Prefer UCRT64 when building with cgo on Windows, probing for the
MinGW compiler per flavor.&lt;/li&gt;
  &lt;li&gt;node: Escape reserved words in parameter names, and zero GValues of options
constructed from objects.&lt;/li&gt;
  &lt;li&gt;python: Marshal null variants as None.&lt;/li&gt;
  &lt;li&gt;swift: Bind the pattern compiler types, as well as variants, lists and
dictionaries. Release owned return values, and declare out params with their
C type so UInt64 out params compile on LP64 Linux.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.19.0 Released</title><link href="https://frida.re/news/2026/09/25/frida-17-19-0-released/" rel="alternate" type="text/html" title="Frida 17.19.0 Released" /><published>2026-09-25T13:15:55+02:00</published><updated>2026-09-25T13:15:55+02:00</updated><id>https://frida.re/news/2026/09/25/frida-17-19-0-released</id><content type="html" xml:base="https://frida.re/news/2026/09/25/frida-17-19-0-released/">&lt;p&gt;This release brings Frida to the PlayStation 5, expands Barebone’s reach
across virtual machines and kernels, and fixes a range of injection and
instrumentation issues.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;prospero: Add a PS5 backend and ship builds of frida-server, portal,
inject, Gadget, and the devkits. The backend can enumerate apps, spawn
programs and apps, and inject agents within the console’s restrictions.&lt;/li&gt;
  &lt;li&gt;barebone: Add support for the Android emulator. Kernel symbol discovery
now handles more Linux images and older kernels, while new hostlink
options include pipe-over-vsock and serial connections.&lt;/li&gt;
  &lt;li&gt;barebone: Extend WinNT support to arm64, including process injection,
and add support for VirtualBox and Parallels guests. Numerous fixes
improve agent reliability across Windows and Linux kernels.&lt;/li&gt;
  &lt;li&gt;device: Add connection-progress events, so applications can show what
Frida is doing while a device connects or a Barebone agent is uploaded.
The new signals are also available in the bindings.&lt;/li&gt;
  &lt;li&gt;fruity: Fix RSD port discovery on macOS 27 and refresh the service
snapshot when a newly published service is not found. A new
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;force_transport=usbmux&lt;/code&gt; channel option lets callers choose usbmux even
when a tunnel is available. Thanks to &lt;a href=&quot;https://twitter.com/bezjaje&quot;&gt;@mrmacete&lt;/a&gt; for the option.&lt;/li&gt;
  &lt;li&gt;darwin: Fix an iOS 27 injection leak that could retain a 40 MB agent
blob after each attach. Also improve memory protection handling and
preserve suspension across policy softening. Thanks to &lt;a href=&quot;https://chaos.social/@jiska&quot;&gt;@jiska&lt;/a&gt;
for these fixes.&lt;/li&gt;
  &lt;li&gt;gum: Improve arm64 relocation and Interceptor handling of function
prologues, including cases where X16 and X17 are both in use. Grafting
now uses Arm64Relocator, allowing PC-relative instructions to be
relocated. Thanks to &lt;a href=&quot;https://chaos.social/@jiska&quot;&gt;@jiska&lt;/a&gt; and &lt;a href=&quot;https://github.com/daniillnull&quot;&gt;@daniillnull&lt;/a&gt; for their work here.&lt;/li&gt;
  &lt;li&gt;interceptor: Track the C stack associated with each frame, improving
handling of stackful coroutines. Thanks to &lt;a href=&quot;https://github.com/wertyutreethgfd&quot;&gt;@wertyutreethgfd&lt;/a&gt; for the
contribution.&lt;/li&gt;
  &lt;li&gt;linux: Reclaim temporary stack and TLS mappings after kernel-assisted
injection, and release the loader region when an agent unloads.
Validate auxiliary-vector program headers before reading them, fixing
a problem exposed by Wine’s preloader. Thanks to &lt;a href=&quot;https://github.com/tntljc&quot;&gt;@tntljc&lt;/a&gt; for the
latter fix.&lt;/li&gt;
  &lt;li&gt;socket: Handle a peer disconnecting between the WebSocket handshake
and connection acceptance instead of aborting the process. Thanks to
&lt;a href=&quot;https://github.com/it4ch1-007&quot;&gt;@it4ch1-007&lt;/a&gt; for the fix.&lt;/li&gt;
  &lt;li&gt;darwin: Use jailbreak-provided memory hooks when available. Thanks to
&lt;a href=&quot;https://github.com/devnoname120&quot;&gt;@devnoname120&lt;/a&gt; for the contribution.&lt;/li&gt;
  &lt;li&gt;gdb: Improve thread selection, timeouts, stop handling, and
compatibility with stubs that do not support binary writes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also fixes for Windows unwinding through Interceptor
trampolines, Swift event delivery and variant lifetimes, generated
bindings, and a variety of platform-specific build issues.&lt;/p&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.18.0 Released</title><link href="https://frida.re/news/2026/09/09/frida-17-18-0-released/" rel="alternate" type="text/html" title="Frida 17.18.0 Released" /><published>2026-09-09T20:37:30+02:00</published><updated>2026-09-09T20:37:30+02:00</updated><id>https://frida.re/news/2026/09/09/frida-17-18-0-released</id><content type="html" xml:base="https://frida.re/news/2026/09/09/frida-17-18-0-released/">&lt;p&gt;Frida 17.18.0 is here, and Barebone takes a big step forward. Our XNU agent can
now be loaded as a macOS kernel extension, Linux agent gains broader
architecture support and access to the kernel’s own type information, and the
backend can instrument both the kernel itself as well as user mode processes
across Linux, XNU, Windows NT, and even Windows 9x. We have also upgraded
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida.Compiler&lt;/code&gt; to TypeScript 7.0 and added a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida.LanguageServer&lt;/code&gt; API
alongside it.&lt;/p&gt;

&lt;p&gt;One of the exciting additions is the ability to build the XNU agent as a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.kext&lt;/code&gt;. Previously, getting it into the kernel meant injecting it from the
outside through a GDB-compatible remote stub, such as QEMU’s, or through a
hardware debugger using JTAG/SWD. Now macOS can load the agent itself, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/frida&lt;/code&gt; provides the channel for configuring and communicating with it.
This opens up another way to use Frida for kernel instrumentation. The kext
currently supports the kernel side; placing agent copies into user processes
still requires the injected XNU agent.&lt;/p&gt;

&lt;p&gt;There is a lot more to Barebone in this release. The injected agents now bring
familiar Frida workflows into guest processes: enumerate them, attach, run
scripts, hook functions, and spawn programs with instrumentation in place before
they start running. This work spans Linux, XNU, Windows NT in both word sizes,
and 32-bit Windows 9x. Linux agent injection now covers x86, x86-64, Arm, and
Arm64, and the Linux agent can be injected into a running kernel as well as
loaded as a kernel module.&lt;/p&gt;

&lt;p&gt;On Linux, scripts can now discover loaded kernel modules and their symbols,
with the module registry tracking drivers as they come and go. The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Btf&lt;/code&gt;
namespace also lets scripts query the kernel’s BTF type information, where
available. Structure sizes, field offsets and types, enums, constants, and
function signatures are available directly from JavaScript. For example:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Btf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;available&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Btf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;struct module size:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;name offset:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getOffsetOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;name field:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;MODULE_STATE_LIVE:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Btf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getConstant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;MODULE_STATE_LIVE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This means scripts can ask the kernel how its structures are laid out, avoiding
hard-coded offsets tied to a particular build. Underneath it is a new GumJS
native API registry, which lets embedders expose namespaces of native functions
independently of the JavaScript runtime in use.&lt;/p&gt;

&lt;p&gt;Meanwhile, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida.Compiler&lt;/code&gt; has been upgraded to TypeScript 7.0. The new
&lt;a href=&quot;https://github.com/frida/frida-core/commit/a987284afa0bd0868a6b65160ff01471b71d10a3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida.LanguageServer&lt;/code&gt;&lt;/a&gt; API brings the same compiler’s language
services to tools embedding Frida. It speaks the Language Server Protocol for
TypeScript and JavaScript projects: create a server for a project directory,
start it, send JSON-RPC messages through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post()&lt;/code&gt;, and receive replies and
notifications through its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;message&lt;/code&gt; signal. This makes it possible to integrate
editor features such as completion with Frida’s bundled typings and compiler
configuration. The compiler and language server also share a parse cache, so
the same file contents do not have to be parsed separately for each.&lt;/p&gt;

&lt;p&gt;Other highlights and fixes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;barebone: Add public APIs for adding and removing Barebone devices, with
caller-supplied IDs, names, and icons. Expose configuration for injected and
resident agents, including explicit hostlink addresses.&lt;/li&gt;
  &lt;li&gt;barebone: Add process spawning and spawn gating across the Linux, XNU, and
Windows agents, plus application enumeration on XNU and Windows and application
launching on XNU.&lt;/li&gt;
  &lt;li&gt;barebone: Improve module and thread observation, fault recovery, process
cleanup, and cloaking of the agent’s own threads and mappings.&lt;/li&gt;
  &lt;li&gt;barebone: Improve transport delivery and wakeups across the agents, including
large messages and binary script-message payloads. Keep resident agents alive
when a session detaches.&lt;/li&gt;
  &lt;li&gt;barebone: Add XNU kernel text patching through writable aliases, and improve
code allocation and pointer authentication at the kernel boundary.&lt;/li&gt;
  &lt;li&gt;barebone: Expose Linux kernel-module symbols from kallsyms and export tables,
and unregister APIs and module observers during teardown.&lt;/li&gt;
  &lt;li&gt;barebone: Move Linux memory operations into the guest, with proper handling of
writable and executable mappings. Extend remapping and patching across x86,
x86-64, Arm, and Arm64.&lt;/li&gt;
  &lt;li&gt;barebone: Halt the guest while accessing QEMU’s physical-memory mode, and fix
kernel text patches being silently dropped when shadow pages originated in
Linux’s linear map.&lt;/li&gt;
  &lt;li&gt;barebone: Place x86 aliases in kernel space, fixing CModules faulting when
accessing their data. Allow virtual-memory scans to span multiple leaf tables.&lt;/li&gt;
  &lt;li&gt;barebone: Add Arm address translation and kernel-space aliases, widen page
addresses in 32-bit remapping requests, and flush Arm instruction caches
directly instead of attempting a userspace syscall from the kernel.&lt;/li&gt;
  &lt;li&gt;barebone: Report the actual stack space available to the JavaScript runtime,
preventing ordinary script recursion from overflowing a Linux kernel stack.&lt;/li&gt;
  &lt;li&gt;barebone: Size the Linux kernel using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_end&lt;/code&gt;, avoiding unrelated mappings that
could make a 32-bit kernel appear gigabytes larger. Read copied kernel images
through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GumElfModule&lt;/code&gt; without dereferencing pointers into the live kernel.&lt;/li&gt;
  &lt;li&gt;barebone: Fix and complete the Linux kernel-module build, including constructor
array boundaries and flavor-specific runtime dependencies.&lt;/li&gt;
  &lt;li&gt;linux: Add kernel-assisted injection when the Frida kernel module is loaded,
falling back to the existing injection paths when it is absent.&lt;/li&gt;
  &lt;li&gt;gdb: Use binary packets for memory writes and honor the target’s register
sizes.&lt;/li&gt;
  &lt;li&gt;interceptor: Fix Arm trampoline addressing when writable and executable views
use different mappings.&lt;/li&gt;
  &lt;li&gt;memory: Skip bad pages when finding pointers. Thanks &lt;a href=&quot;https://github.com/IPMegladon&quot;&gt;@IPMegladon&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;memory: Allow wildcards at scan pattern edges, including in Barebone. Thanks
&lt;a href=&quot;https://github.com/Xoffio&quot;&gt;@Xoffio&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;arm64: Avoid BTI where no landing pad is available. Thanks &lt;a href=&quot;https://github.com/inforcqb&quot;&gt;@inforcqb&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;arm64: Detect branches into the instructions being relocated, so Interceptor
can choose a smaller redirect instead of branching into overwritten code and
crashing. Thanks &lt;a href=&quot;https://github.com/WHW0x455&quot;&gt;@WHW0x455&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;cmodule: Move CModule from GumJS into Gum, making it available independently of
the JavaScript bindings. Thanks &lt;a href=&quot;https://github.com/cputnam-a11y&quot;&gt;@cputnam-a11y&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;elf-module: Read program headers from the file, fixing modules whose headers
have been moved by tools such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patchelf&lt;/code&gt;. Bound the fallback read when only
a live mapping is available. Thanks &lt;a href=&quot;https://github.com/tracyliving&quot;&gt;@tracyliving&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;windows: Tweak ACLs to improve injection success rate. Thanks
&lt;a href=&quot;https://github.com/jamiechapmanbrn&quot;&gt;@jamiechapmanbrn&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;python: Fix typing imports on Python versions older than 3.11.&lt;/li&gt;
  &lt;li&gt;ci: Build the XNU kernel extension, additional Linux agents, and the required
Barebone SDKs and devkits. Enable the Barebone backend on Android.&lt;/li&gt;
  &lt;li&gt;deps: Slim down Capstone in Barebone SDKs, reducing its archive from roughly
29 MB to 4.4 MB. Let freestanding GLib builds use the C library’s smaller
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; implementation, and trim locale and filename-conversion support.&lt;/li&gt;
  &lt;li&gt;deps: Optimize QuickJS to reduce its stack consumption, and tweak GLib to
reduce our footprint in Barebone scenarios.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.17.0 Released</title><link href="https://frida.re/news/2026/08/05/frida-17-17-0-released/" rel="alternate" type="text/html" title="Frida 17.17.0 Released" /><published>2026-08-05T00:47:29+02:00</published><updated>2026-08-05T00:47:29+02:00</updated><id>https://frida.re/news/2026/08/05/frida-17-17-0-released</id><content type="html" xml:base="https://frida.re/news/2026/08/05/frida-17-17-0-released/">&lt;p&gt;This is a big release with lots of bare-metal goodness. The Barebone agent—
written in Rust and embedding the GumJS devkit—previously supported only XNU.
It can now also run in the Linux kernel, where a small C shim provides the
kernel glue.&lt;/p&gt;

&lt;p&gt;The agent is packaged as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ko&lt;/code&gt;: load it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;insmod&lt;/code&gt;, then exchange
length-prefixed GVariant messages through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/frida&lt;/code&gt;. Configure the Barebone
backend to use this transport, and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frida-server --device=barebone&lt;/code&gt; on the
device. Here it is running on my Pixel 6 Pro:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/barebone-linux-kernel.png&quot; alt=&quot;linux-kernel&quot; title=&quot;Linux kernel&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;build-the-module-for-your-device&quot;&gt;Build the module for your device&lt;/h2&gt;

&lt;p&gt;The release page has a GumJS devkit for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;none-arm64-softfloat&lt;/code&gt; target. You
do not have to build Gum yourself. The steps below make a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frida-agent.ko&lt;/code&gt; for
a Pixel 6 Pro. Other arm64 Linux systems use the same steps with a different
kernel.&lt;/p&gt;

&lt;p&gt;Do the build on an x86-64 Linux host. The kernel build tree contains x86-64
programs.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Install the tools:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get install build-essential clang binutils-aarch64-linux-gnu
rustup target add aarch64-unknown-none
rustup component add rust-src
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Your clang must be version 19 or newer. GCC does not implement the
soft-float ABI.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Download the source:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone --recurse-submodules https://github.com/frida/frida-core.git
cd frida-core
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Download the devkit:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;version=17.17.0
base=https://github.com/frida/frida/releases/download/$version
curl -LO $base/frida-gumjs-devkit-$version-none-arm64-softfloat.tar.xz
mkdir -p ~/gumjs-devkit
tar -C ~/gumjs-devkit -xf frida-gumjs-devkit-$version-none-arm64-softfloat.tar.xz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Download the SDK:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;releng/deps.py sync sdk none-arm64-softfloat_nopic ~/sdk-none-arm64-softfloat_nopic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The SDK contains picolibc and the compiler-rt builtins. The devkit needs
them.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Read the kernel version from the device:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell uname -r
6.1.145-android14-11-gc1de4747ac59-ab14219743
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The name ends with the GKI commit and the build number. Here the commit is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1de4747ac59&lt;/code&gt;. The build number is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;14219743&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Download the kernel files:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;commit=c1de4747ac59
build=14219743
ci=https://ci.android.com/builds/submitted/$build/kernel_aarch64/latest/raw
mkdir -p ~/kernel-prepared ~/kernel-source
curl -sSL $ci/modules_prepare_outdir.tar.gz | tar -xz -C ~/kernel-prepared
curl -sSL $ci/kernel_aarch64_Module.symvers -o ~/kernel-prepared/Module.symvers
curl -sSL https://android.googlesource.com/kernel/common/+archive/$commit.tar.gz \
    | tar -xz -C ~/kernel-source
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Build the module:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make -C src/barebone/agent/linux \
    FRIDA_SDK=$HOME/sdk-none-arm64-softfloat_nopic \
    GUMJS_DEVKIT_DIR=$HOME/gumjs-devkit \
    AGENT_LD=aarch64-linux-gnu-ld \
    AGENT_AR=aarch64-linux-gnu-ar \
    AGENT_NM=aarch64-linux-gnu-nm \
    AGENT_OBJCOPY=aarch64-linux-gnu-objcopy \
    KDIR=$HOME/kernel-source \
    KOUT=$HOME/kernel-prepared \
    LLVM=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Load the module:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb push src/barebone/agent/linux/frida-agent.ko /data/local/tmp/
adb shell su -c &apos;insmod /data/local/tmp/frida-agent.ko&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The module loads only on the kernel build that you made it for. The kernel
compares the version string exactly. A different build of the same kernel
branch does not work.&lt;/p&gt;

&lt;p&gt;For more information, read the &lt;a href=&quot;https://github.com/frida/frida-core/blob/main/src/barebone/agent/linux/README.md&quot;&gt;module README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Full changelog:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;gumjs: Fix a detach hang when a native fault inside JS is recovered by a
later handler. We now rebalance the Interceptor transaction when the thread
survives, instead of ending it twice. Kudos to &lt;a href=&quot;https://github.com/pandasauce&quot;&gt;@pandasauce&lt;/a&gt; for reporting
the issue and helping track it down.&lt;/li&gt;
  &lt;li&gt;arm64: Detect branches into the range being relocated, preventing Interceptor
from rewriting a branch so that it lands in the middle of its own redirect
patch. Thanks to &lt;a href=&quot;https://github.com/WHW0x455&quot;&gt;@WHW0x455&lt;/a&gt; for this fix.&lt;/li&gt;
  &lt;li&gt;python: Fix the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linker_notifier_offsets&lt;/code&gt; keyword argument to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attach()&lt;/code&gt;,
restore the default port for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Script.enable_debugger()&lt;/code&gt;, and reinstate
marshalling of certificate options for remote devices and related APIs.&lt;/li&gt;
  &lt;li&gt;barebone: Add support for running the agent as a Linux kernel module. The
agent now starts inside the target as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ko&lt;/code&gt;, exposes a character device for
transport, and can be reached through a regular
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frida-server --device=barebone&lt;/code&gt; instance.&lt;/li&gt;
  &lt;li&gt;deps: Add a soft-float bare-metal SDK comprising picolibc and compiler-rt.
This gives the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;none-arm64-softfloat&lt;/code&gt; flavour a libc and runtime that agree
on passing floating-point values through general-purpose registers.&lt;/li&gt;
  &lt;li&gt;deps: Build the soft-float SDK in CI, check for published bundles before
spending time installing a toolchain, keep libc headers out of devkit
headers, use the SDK as the sysroot, and ensure configure-time link checks
resolve libc correctly.&lt;/li&gt;
  &lt;li&gt;deps: Bump GLib, libffi, and QuickJS for freestanding fixes, vector assembler
directive fixes, the precedence-climbing parser, and the corresponding x18
fix.&lt;/li&gt;
  &lt;li&gt;arm64: Avoid FP and SIMD code on soft-float targets by using scalar fallbacks
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memcpy&lt;/code&gt;, pointer scanning, and Interceptor’s register shuffling.&lt;/li&gt;
  &lt;li&gt;gumjs: Bound the QuickJS stack on bare metal, re-enabling its stack check so
the parser stops before exhausting the small stacks such hosts may provide.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.16.4 Released</title><link href="https://frida.re/news/2026/07/22/frida-17-16-4-released/" rel="alternate" type="text/html" title="Frida 17.16.4 Released" /><published>2026-07-22T00:30:23+02:00</published><updated>2026-07-22T00:30:23+02:00</updated><id>https://frida.re/news/2026/07/22/frida-17-16-4-released</id><content type="html" xml:base="https://frida.re/news/2026/07/22/frida-17-16-4-released/">&lt;p&gt;Quick bug-fix release to restore some Python binding API and typing surface
area that regressed in the recent bindgen rewrite:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;bindgen: Restore the remaining public names. The cancellable decorator,
RPCResult, make_rpc_call_request(), make_auth_callback(), and
ScriptExportsAsync are now exposed again from frida.core.&lt;/li&gt;
  &lt;li&gt;bindgen: Generate signal callback overloads for the facade’s on()/off()
helpers. This means malformed signal handlers should now be caught by type
checkers instead of silently passing as any callable.&lt;/li&gt;
  &lt;li&gt;bindgen: Restore missing facade members omitted by the .gir-based generator:
get_device(), get_device_matching(), enumerate_devices(), shutdown(),
Cancellable.connect(), and Cancellable.disconnect().&lt;/li&gt;
  &lt;li&gt;bindgen: Restore the facade typing surface. The generated package once again
ships the expected type aliases and annotations, including module functions,
read-only options properties, and the _frida.pyi entries that went missing.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.16.3 Released</title><link href="https://frida.re/news/2026/07/20/frida-17-16-3-released/" rel="alternate" type="text/html" title="Frida 17.16.3 Released" /><published>2026-07-20T17:56:10+02:00</published><updated>2026-07-20T17:56:10+02:00</updated><id>https://frida.re/news/2026/07/20/frida-17-16-3-released</id><content type="html" xml:base="https://frida.re/news/2026/07/20/frida-17-16-3-released/">&lt;p&gt;Another quick bug-fix release, addressing two issues in the Python bindings:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;bindgen: Fixed marshalling of option keyword arguments. None values are now
omitted instead of being passed to typed setters.&lt;/li&gt;
  &lt;li&gt;bindgen: Fixed collection-valued keyword arguments by mapping them to the
appropriate select_ or add_ methods while traversing the parent chain.
This affects specs, omits, externals, PIDs, and identifiers.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry><entry><title type="html">Frida 17.16.2 Released</title><link href="https://frida.re/news/2026/07/19/frida-17-16-2-released/" rel="alternate" type="text/html" title="Frida 17.16.2 Released" /><published>2026-07-19T22:25:34+02:00</published><updated>2026-07-19T22:25:34+02:00</updated><id>https://frida.re/news/2026/07/19/frida-17-16-2-released</id><content type="html" xml:base="https://frida.re/news/2026/07/19/frida-17-16-2-released/">&lt;p&gt;Another quick bug-fix release, fixing an issue where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frida-helper&lt;/code&gt; on Darwin
and Linux kept the embedder’s stdio pipes open.&lt;/p&gt;

&lt;p&gt;The helper previously inherited these streams at launch so they could later be
used by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Device#spawn()&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdio=&apos;inherit&apos;&lt;/code&gt;. The streams are now passed to
the helper with each such request instead.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;darwin: Redirect the helper’s own stdin, stdout, and stderr to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/null&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;linux: Apply the same fix as on Darwin.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>oleavr</name></author><category term="release" /></entry></feed>