<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Naren Sirigere's blog</title><link>http://naren.wiki/tags/gsoc/</link><description>All blog posts</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>© 2025 - 2026 by Naren Sirigere</copyright><lastBuildDate>Wed, 17 Jun 2026 00:00:00 +0530</lastBuildDate><atom:link href="http://naren.wiki/tags/gsoc/index.xml" rel="self" type="application/rss+xml"/><item><title>RTTI and Devirtualization in Objective-C</title><link>http://naren.wiki/posts/objc/</link><pubDate>Wed, 17 Jun 2026 00:00:00 +0530</pubDate><guid>http://naren.wiki/posts/objc/</guid><description>&lt;h2 id="object-model"&gt;Object Model&lt;/h2&gt;
&lt;p&gt;Unlike C++, ObjC classes are runtime objects, not compile-time abstractions. The compiler emits class metadata into Mach-O sections (&lt;code&gt;__objc_data&lt;/code&gt;, &lt;code&gt;__objc_const&lt;/code&gt;) as &lt;code&gt;struct objc_class&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;objc_class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="n"&gt;isa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; metaclass
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="n"&gt;superclass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; parent class
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;uintptr_t&lt;/span&gt; &lt;span class="n"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// class_rw_t / class_ro_t
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;superclass&lt;/code&gt; (offset +8): parent&amp;rsquo;s &lt;code&gt;objc_class&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isa&lt;/code&gt;: points to the &lt;strong&gt;metaclass&lt;/strong&gt; — a hidden class object whose instance methods are this class&amp;rsquo;s &lt;em&gt;class methods&lt;/em&gt; (&lt;code&gt;+alloc&lt;/code&gt;, etc). Metaclasses have their own superclass chain.&lt;/li&gt;
&lt;li&gt;Symbols: &lt;code&gt;_OBJC_CLASS_$_Dog&lt;/code&gt;, &lt;code&gt;_OBJC_METACLASS_$_Dog&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="objc_msgsendsuper2"&gt;objc_msgSendSuper2&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;[super speak]&lt;/code&gt; does not compile to &lt;code&gt;objc_msgSend&lt;/code&gt;. Modern ARM64/Apple runtimes use &lt;code&gt;objc_msgSendSuper2&lt;/code&gt;, passing a stack-allocated struct:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;objc_super2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// self
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="n"&gt;current_class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// class where the call site lives (Dog, not Animal)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At runtime, &lt;code&gt;objc_msgSendSuper2&lt;/code&gt; dereferences &lt;code&gt;current_class-&amp;gt;superclass&lt;/code&gt; and searches upward for the selector. &lt;code&gt;current_class&lt;/code&gt; (not the superclass) is passed so the compiler avoids resolving the superclass statically — which means static analysis tools must reconstruct the inheritance edge themselves to devirtualize the call.&lt;/p&gt;
&lt;h2 id="rtti-recovery-librzarchobjc_rttic"&gt;RTTI Recovery (&lt;code&gt;librz/arch/objc_rtti.c&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. Resolve superclass pointer of a metaclass symbol&lt;/strong&gt; — read 8 bytes at &lt;code&gt;vaddr+8&lt;/code&gt;, match against known symbol vaddrs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RzBinSymbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;get_objc_superclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RzCore&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RzPVector&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RzBinSymbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;meta_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ut64&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;rz_io_nread_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;meta_info&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vaddr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ut8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;rz_pvector_foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RzBinSymbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;super_meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;super_meta&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;super_meta&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vaddr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;super_meta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2. Register the base-class edge&lt;/strong&gt; — strip &lt;code&gt;_OBJC_METACLASS_$_&lt;/code&gt; prefix, call &lt;code&gt;rz_analysis_class_base_set&lt;/code&gt; with offset 0 (ObjC single inheritance shares the base pointer):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;add_objc_superclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RzAnalysis&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RzPVector&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RzBinSymbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;meta_class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RzBinSymbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;meta_superclass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;strstr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta_superclass&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;_OBJC_METACLASS_$_&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta_class&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;_OBJC_METACLASS_$_&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;superclass_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rz_str_dup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta_superclass&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;_OBJC_METACLASS_$_&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RzAnalysisBaseClass&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;superclass_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;rz_analysis_class_base_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;rz_analysis_class_base_fini&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3. Entry point&lt;/strong&gt; — iterate all symbols, filter &lt;code&gt;_OBJC_METACLASS_$_*&lt;/code&gt;, wire into &lt;code&gt;rz_analysis_rtti_objc()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;RZ_API&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;rz_analysis_rtti_objc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RZ_NULLABLE&lt;/span&gt; &lt;span class="n"&gt;RzAnalysis&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RzPVector&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rz_analysis_class_get_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RzBinObject&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rz_bin_cur_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;binb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RzPVector&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rz_bin_object_get_symbols&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;rz_pvector_foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RzBinSymbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sym&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RzBinSymbol&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;meta_superclass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;strstr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;_OBJC_METACLASS_$_&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;meta_superclass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_objc_superclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta_superclass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;add_objc_superclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;meta_superclass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;rz_pvector_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hooked into &lt;code&gt;librz/arch/rtti.c&lt;/code&gt; dispatch:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;RZ_BIN_LANGUAGE_SWIFT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;rz_analysis_rtti_swift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nl"&gt;RZ_BIN_LANGUAGE_OBJC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;rz_analysis_rtti_objc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="c1"&gt;// fallthrough
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="result"&gt;Result&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[0x100000000]&amp;gt; aaa
[0x100000000]&amp;gt; acll
[Animal]
nth addr vt_offset type name
-----------------------------------------
1 0x100003e1c ---------- DEFAULT speak
[Dog: Animal]
nth addr vt_offset type name
-----------------------------------------
1 0x100003e48 ---------- DEFAULT speak
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;[Dog: Animal]&lt;/code&gt; — inheritance is now explicit in Rizin&amp;rsquo;s class DB.&lt;/p&gt;
&lt;h2 id="why-it-matters"&gt;Why It Matters&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Devirtualizing &lt;code&gt;objc_msgSendSuper2&lt;/code&gt;&lt;/strong&gt;: given &lt;code&gt;current_class&lt;/code&gt; at a call site, look up its base class and resolve the selector against the parent&amp;rsquo;s method list instead of leaving the call unresolved.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Override detection&lt;/strong&gt;: directly see which subclasses override which parent methods.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Xref precision&lt;/strong&gt;: a &lt;code&gt;@selector(speak)&lt;/code&gt; call site can be narrowed to candidates within the relevant class hierarchy instead of matching every &lt;code&gt;speak&lt;/code&gt; implementation in the binary.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>The up-to-date DLang DMD Mangling Scheme *</title><link>http://naren.wiki/posts/dmd_mangling_scheme/</link><pubDate>Sat, 13 Jun 2026 00:00:00 +0530</pubDate><guid>http://naren.wiki/posts/dmd_mangling_scheme/</guid><description>&lt;p&gt;An updated reference for the Dlang DMD name mangling ABI.&lt;/p&gt;
&lt;p&gt;* At least up to 2026-06-13&lt;/p&gt;
&lt;h3 id="grammar-notation"&gt;Grammar Notation&lt;/h3&gt;
&lt;p&gt;This specification uses standard EBNF. Terminal characters are literal characters in the mangled string.&lt;/p&gt;
&lt;h3 id="1-the-root-symbol"&gt;1. The Root Symbol&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;MangledName:
_D QualifiedName [ M ] [ Type ] [ Z ]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Note: &lt;code&gt;M&lt;/code&gt; denotes a member function.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="2-names-and-symbols"&gt;2. Names and Symbols&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;QualifiedName:
SymbolFunctionName { SymbolFunctionName }
SymbolFunctionName:
SymbolName [ M TypeModifier ] [ CallingConvention FuncAttrs (Parameters) ParamClose ]
SymbolName:
0
LName
BackRefSymbol
TemplateInstanceName
LName:
Number Name
0 // __anonymous
___S Number // Special anonymous symbol
Number:
Digit { Digit }
BackRefSymbol:
Q Base26Pos
Base26Pos:
{ UpperCaseAlpha } LowerCaseAlpha // Upper = A-Z (0-25), Lower = a-z (0-25, terminates)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="3-types-and-modifiers"&gt;3. Types and Modifiers&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Type:
TypeModifiers Type
BasicType
DerivedType
FunctionType
DelegateType
VectorType
BackRefType
BasicType:
v | g | h | s | t | i | k | l | m | f | d | e | o | p | j | q | r | c | b | a | u | w | n | z i | z k
DerivedType:
A Type // Dynamic Array: Type[]
P Type // Pointer: Type*
G Number Type // Static Array: Type[Number]
H Type Type // Associative Array: Type[Type]
I QualifiedName // Identifier
C QualifiedName // Class
S QualifiedName // Struct
E QualifiedName // Enum
T QualifiedName // Typedef
B (Parameters) Z // Tuple
VectorType:
N h Type // __vector(Type)
BackRefType:
Q Base26Pos
TypeModifiers:
x // const
y // immutable
O // shared
O x // shared const
O N g // shared inout
O N g x // shared inout const
N g // inout
N g x // inout const
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="4-functions-and-delegates"&gt;4. Functions and Delegates&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;CallingConvention:
F // D
U // C
W // Windows
R // C++
Y // Objective-C
FunctionType:
CallingConvention FuncAttrs (Parameters) ParamClose Type // (args) return_type
DelegateType:
D [ TypeModifiers ] [ CallingConvention ] FuncAttrs (Parameters) ParamClose Type
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="5-function-attributes"&gt;5. Function Attributes&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;FuncAttrs:
{ FuncAttr }
FuncAttr:
N a // pure
N b // nothrow
N c // ref
N d // @property
N e // @trusted
N f // @safe
N i // @nogc
N j // return
N j N l // return scope
N l // scope
N l N j // scope return
N m // @live
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="6-parameters"&gt;6. Parameters&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Parameters:
{ Parameter }
Parameter:
[ ParamStorageClass ] Type
ParamStorageClass:
M N k J // scope return out
M N k K // scope return ref
N k J // return out
N k K // return ref
N k M J // return scope out
N k M K // return scope ref
N k M // return scope
M // scope
N k // return
I // in
I K // in ref
J // out
K // ref
L // lazy
ParamClose:
X // ...) (variadic)
Y // , ...) (C-style variadic)
Z // ) (standard)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="7-templates"&gt;7. Templates&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;TemplateInstanceName:
TemplateID SymbolName TemplateArgs [ Z ]
TemplateID:
__T | __U | T | U
TemplateArgs:
{ [ H ] TemplateArg }
TemplateArg:
T Type // Type argument
V TypeChar Type Value // Value argument
S QualifiedName // Symbol argument
S _ D QualifiedName [Z] // Fully qualified symbol
X Number Name // Externally linked LName
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="8-values-and-literals"&gt;8. Values and Literals&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Value:
n // null
i Number // positive integer
N Number // negative integer
Number // positive integer (shorthand)
b Number // boolean (0/1)
e HexFloat // real
c HexFloat c HexFloat // complex real
a Number _ HexString // char string
w Number _ HexString // wchar string
d Number _ HexString // dchar string
A Number { Value } // Array
H Number { Value : Value } // Associative Array
S Number { Value } // Struct
HexFloat:
N A N // real.nan
I N F // real.infinity
N I N F // -real.infinity
[ N ] HexDigits P [ N ] Number // Hexadecimal float (e.g., 0x...p+/-...)
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h3 id="deviations--additions-from-the-official-spec"&gt;Deviations &amp;amp; Additions from the Official Spec&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parameter Storage Classes:&lt;/strong&gt; Added complex, undocumented combinations (e.g., &lt;code&gt;M N k J&lt;/code&gt; for &lt;code&gt;scope return out&lt;/code&gt;, &lt;code&gt;I K&lt;/code&gt; for &lt;code&gt;in ref&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type Back References:&lt;/strong&gt; Specified that &lt;code&gt;Q&lt;/code&gt; compresses types (&lt;code&gt;BackRefType&lt;/code&gt;), not just symbols.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New Attributes:&lt;/strong&gt; Added &lt;code&gt;@live&lt;/code&gt; (&lt;code&gt;N m&lt;/code&gt;), &lt;code&gt;return scope&lt;/code&gt; (&lt;code&gt;N j N l&lt;/code&gt;), and &lt;code&gt;scope return&lt;/code&gt; (&lt;code&gt;N l N j&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Template Values (&lt;code&gt;V&lt;/code&gt;):&lt;/strong&gt; Added detailed grammar for arrays (&lt;code&gt;A&lt;/code&gt;), associative arrays (&lt;code&gt;H&lt;/code&gt;), structs (&lt;code&gt;S&lt;/code&gt;), and exact hex float configurations (base-16 exponents, &lt;code&gt;N A N&lt;/code&gt;, &lt;code&gt;I N F&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vectors &amp;amp; 128-bit Ints:&lt;/strong&gt; Added &lt;code&gt;__vector(Type)&lt;/code&gt; (&lt;code&gt;N h&lt;/code&gt;), &lt;code&gt;cent&lt;/code&gt; (&lt;code&gt;z i&lt;/code&gt;), and &lt;code&gt;ucent&lt;/code&gt; (&lt;code&gt;z k&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anonymous Symbols:&lt;/strong&gt; Included &lt;code&gt;___S Number&lt;/code&gt; for special anonymous scopes.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="implementation"&gt;Implementation&lt;/h3&gt;
&lt;p&gt;My C implementation of a demangler based on this DMD specification can be found here: &lt;a href="https://github.com/rizinorg/rz-libdemangle/blob/main/src/d/dmd.c"&gt;rz-libdemangle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This parser was developed as part of my GSoC'26 project for the &lt;a href="https://rizin.re/"&gt;Rizin&lt;/a&gt; reverse engineering framework.&lt;/p&gt;</description></item></channel></rss>