<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Digital Cabin - programing</title>
<link rel="alternate" href="https://cabin.digital"/>
<link rel="self" href="https://cabin.digital/tags/programing.xml"/>
<id>https://cabin.digital/</id>
<updated>2025-06-17T23:00:00Z</updated>
<generator uri="https://cabin.digital/golog.html" version="1.10.1beta">golog</generator>
<subtitle>Comfy cabin in a rough digital ocean</subtitle>
<author>
<name>dweller</name>
</author>
<category term="asm"/>
<category term="sh"/>
<category term="bench"/>
<category term="programing"/>
<category term="dev"/>
<category term="c"/>
<category term="linux"/>
<category term="x86"/>
<entry>
<id>https://cabin.digital/tags/programing.xml:::https://cabin.digital/log/small_elfs.html</id>
<link rel="alternate" href="https://cabin.digital/log/small_elfs.html"/>
<title>Small ELFs</title>
<updated>2025-06-17T23:00:00Z</updated>
<author>
<name>dweller</name>
</author>
<category term="programing"/>
<category term="dev"/>
<category term="c"/>
<category term="linux"/>
<category term="x86"/>
<category term="asm"/>
<category term="sh"/>
<category term="bench"/>
<content type="html"><![CDATA[<p>In a <a href="/log/flatbin.html">previous</a> log I mentioned that I was trying to make small
<a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format">ELF</a>s. Well that also got me thinking
how big is an average ELF. So I spent too much time on writing some sh(1) and awk(1) scripts, and
this is the result:</p>

<table class="scroll-indicator">
<thead>
<tr>
<th>lang</th>
<th>size</th>
<th>rundeps</th>
<th>↓total</th>
<th>type</th>
<th>arch</th>
<th>linkage</th>
<th>debug?</th>
<th>strip?</th>
<th>buildT</th>
<th>runT/100</th>
</tr>
</thead>
<tbody><tr>
<td>nasm-elf32-s</td>
<td>134</td>
<td>0</td>
<td>134</td>
<td>ELF32l</td>
<td>Intel 80386</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>6.05ms</td>
<td>134.12µs</td>
</tr>
<tr>
<td>nasm-elf32</td>
<td>141</td>
<td>0</td>
<td>141</td>
<td>ELF32l</td>
<td>Intel 80386</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>7.99ms</td>
<td>165.81µs</td>
</tr>
<tr>
<td>nasm-elf-s</td>
<td>165</td>
<td>0</td>
<td>165</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>14.65ms</td>
<td>131.77µs</td>
</tr>
<tr>
<td>nasm-elf</td>
<td>173</td>
<td>0</td>
<td>173</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>7.66ms</td>
<td>150.67µs</td>
</tr>
<tr>
<td>jmpld</td>
<td>56</td>
<td>308</td>
<td>364</td>
<td>bin</td>
<td>jmpld</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>19.09ms</td>
<td>144.06µs</td>
</tr>
<tr>
<td>bld</td>
<td>54</td>
<td>493</td>
<td>547</td>
<td>bin</td>
<td>bld</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>9.28ms</td>
<td>233.59µs</td>
</tr>
<tr>
<td>nasm</td>
<td>8.30KB</td>
<td>0</td>
<td>8.30KB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>14.62ms</td>
<td>139.83µs</td>
</tr>
<tr>
<td>c-gcc-nlibc</td>
<td>8.72KB</td>
<td>0</td>
<td>8.72KB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>50.08ms</td>
<td>180.19µs</td>
</tr>
<tr>
<td>c-musl-st</td>
<td>13.45KB</td>
<td>0</td>
<td>13.45KB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>41.59ms</td>
<td>190.95µs</td>
</tr>
<tr>
<td>jmpld-c</td>
<td>56</td>
<td>17.45KB</td>
<td>17.50KB</td>
<td>bin</td>
<td>jmpld</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>83.34ms</td>
<td>164.79µs</td>
</tr>
<tr>
<td>c-gcc-st</td>
<td>648.45KB</td>
<td>0</td>
<td>648.45KB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>109.54ms</td>
<td>304.16µs</td>
</tr>
<tr>
<td>c-clang-st</td>
<td>656.55KB</td>
<td>0</td>
<td>656.55KB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>141.96ms</td>
<td>301.99µs</td>
</tr>
<tr>
<td>oksh-musl-st</td>
<td>42</td>
<td>1010.13KB</td>
<td>1010.17KB</td>
<td>script</td>
<td>oksh</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>4.07ms</td>
<td>571.29µs</td>
</tr>
<tr>
<td>go-s</td>
<td>1.36MB</td>
<td>0</td>
<td>1.36MB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>206.59ms</td>
<td>1.08ms</td>
</tr>
<tr>
<td>c++gcc-st</td>
<td>2.10MB</td>
<td>0</td>
<td>2.10MB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>707.85ms</td>
<td>560.04µs</td>
</tr>
<tr>
<td>go</td>
<td>2.10MB</td>
<td>0</td>
<td>2.10MB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>yes</td>
<td>no</td>
<td>257.03ms</td>
<td>1.07ms</td>
</tr>
<tr>
<td>c++clang-st</td>
<td>2.14MB</td>
<td>0</td>
<td>2.14MB</td>
<td>ELF64l</td>
<td>x86-64</td>
<td>static</td>
<td>no</td>
<td>yes</td>
<td>722.34ms</td>
<td>563.63µs</td>
</tr>
<tr>
<td>rust-nstd-s</td>
<td>14.05KB</td>
<td>13.45MB</td>
<td>13.46MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>163.81ms</td>
<td>598.39µs</td>
</tr>
<tr>
<td>c-gcc-s-lto</td>
<td>14.14KB</td>
<td>13.45MB</td>
<td>13.47MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>104.36ms</td>
<td>479.64µs</td>
</tr>
<tr>
<td>c-gcc-s</td>
<td>14.14KB</td>
<td>13.45MB</td>
<td>13.47MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>66.75ms</td>
<td>472.23µs</td>
</tr>
<tr>
<td>c-clang-s</td>
<td>14.16KB</td>
<td>13.45MB</td>
<td>13.47MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>95.86ms</td>
<td>458.92µs</td>
</tr>
<tr>
<td>rust-nstd</td>
<td>19.70KB</td>
<td>13.45MB</td>
<td>13.47MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>82.25ms</td>
<td>457.37µs</td>
</tr>
<tr>
<td>c-gcc</td>
<td>19.88KB</td>
<td>13.45MB</td>
<td>13.47MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>63.22ms</td>
<td>621.80µs</td>
</tr>
<tr>
<td>c-clang</td>
<td>19.89KB</td>
<td>13.45MB</td>
<td>13.47MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>90.55ms</td>
<td>554.57µs</td>
</tr>
<tr>
<td>c-gcc-g</td>
<td>48.71KB</td>
<td>13.45MB</td>
<td>13.50MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>77.53ms</td>
<td>511.37µs</td>
</tr>
<tr>
<td>sh-unix</td>
<td>23</td>
<td>13.57MB</td>
<td>13.57MB</td>
<td>script</td>
<td>dash</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>3.11ms</td>
<td>729.54µs</td>
</tr>
<tr>
<td>sh</td>
<td>34</td>
<td>13.57MB</td>
<td>13.57MB</td>
<td>script</td>
<td>dash</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>2.71ms</td>
<td>721.37µs</td>
</tr>
<tr>
<td>rust-s</td>
<td>312.67KB</td>
<td>13.63MB</td>
<td>13.93MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>2.97s</td>
<td>658.44µs</td>
</tr>
<tr>
<td>rust-s-nlto</td>
<td>360.77KB</td>
<td>13.63MB</td>
<td>13.98MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>160.25ms</td>
<td>753.09µs</td>
</tr>
<tr>
<td>rust</td>
<td>436.70KB</td>
<td>13.63MB</td>
<td>14.05MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>139.50ms</td>
<td>797.12µs</td>
</tr>
<tr>
<td>c++gcc-s</td>
<td>14.15KB</td>
<td>20.21MB</td>
<td>20.22MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>549.65ms</td>
<td>1.22ms</td>
</tr>
<tr>
<td>c++clang-s</td>
<td>14.19KB</td>
<td>20.21MB</td>
<td>20.22MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>no</td>
<td>yes</td>
<td>612.06ms</td>
<td>1.15ms</td>
</tr>
<tr>
<td>c++clang</td>
<td>20.21KB</td>
<td>20.21MB</td>
<td>20.23MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>558.83ms</td>
<td>1.14ms</td>
</tr>
<tr>
<td>c++gcc</td>
<td>20.40KB</td>
<td>20.21MB</td>
<td>20.23MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>529.38ms</td>
<td>1.22ms</td>
</tr>
<tr>
<td>c++clang-g</td>
<td>35.40KB</td>
<td>20.21MB</td>
<td>20.24MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>629.34ms</td>
<td>1.41ms</td>
</tr>
<tr>
<td>c++gcc-g</td>
<td>148.93KB</td>
<td>20.21MB</td>
<td>20.35MB</td>
<td>ELF64l-PIE</td>
<td>x86-64</td>
<td>dynamic</td>
<td>yes</td>
<td>no</td>
<td>622.06ms</td>
<td>1.17ms</td>
</tr>
<tr>
<td>tail</td>
<td>32</td>
<td>20.55MB</td>
<td>20.55MB</td>
<td>script</td>
<td>tail</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>3.19ms</td>
<td>724.24µs</td>
</tr>
<tr>
<td>bash</td>
<td>40</td>
<td>21.89MB</td>
<td>21.89MB</td>
<td>script</td>
<td>bash</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>2.16ms</td>
<td>2.01ms</td>
</tr>
<tr>
<td>zsh</td>
<td>39</td>
<td>25.42MB</td>
<td>25.42MB</td>
<td>script</td>
<td>zsh</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>3.19ms</td>
<td>2.45ms</td>
</tr>
<tr>
<td>perl</td>
<td>42</td>
<td>27.96MB</td>
<td>27.96MB</td>
<td>script</td>
<td>perl</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>2.65ms</td>
<td>1.71ms</td>
</tr>
<tr>
<td>ruby</td>
<td>40</td>
<td>29.07MB</td>
<td>29.07MB</td>
<td>script</td>
<td>ruby</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>5.30ms</td>
<td>57.78ms</td>
</tr>
<tr>
<td>py3</td>
<td>45</td>
<td>29.17MB</td>
<td>29.17MB</td>
<td>script</td>
<td>python3.13</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>4.94ms</td>
<td>14.39ms</td>
</tr>
<tr>
<td>nodejs</td>
<td>49</td>
<td>177.31MB</td>
<td>177.31MB</td>
<td>script</td>
<td>node</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>7.88ms</td>
<td>26.03ms</td>
</tr>
<tr>
<td>c-musl-s</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>FAIL</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>c-musl</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>FAIL</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>rust-nstd-st</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>FAIL</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>rust-st</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>FAIL</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>rust-tiny</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>FAIL</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
</tbody></table>

<p>Explanation of naming:</p>

<ul>
<li>-g = debug;</li>
<li>-s = small (stripped + something like -Os if available and I knew of it)</li>
<li>-st = static build</li>
<li>-noX = without X, like -nolibc = without any libc</li>
</ul>

<p>Some things failed because:</p>

<ol>
<li>I only had static musl built, so dynamic failed;</li>
<li>I didn&rsquo;t know how to coax some rust builds since I don&rsquo;t use it.</li>
</ol>

<p><strong>A big caveat regarding the &ldquo;runtime&rdquo;.</strong>
The &ldquo;runtime&rdquo; benchmarks are more of a benchmark of shell parsing, execve(2) and fork(2)ing and
runtime start up of the program, since the program doesn&rsquo;t really do anything. Still it does show
how slow the startup is, I guess it matters for shell scripts/tools.</p>

<p>You can check out the source for this all at my
<a href="https://cabin.digital/git/elfsizes.git/tree/">git repo</a>.</p>

<p>IDK if it has any use except to, maybe, show that static binaries are not as bloated as people often
think. (Because any decent lib will be split into many .o and only used code will be linked. + LTO)
Which is just another reason to use them over the death of us all that is dynamic linking.</p>

<p><script src="/js/tablesort.js"></script></p>
]]></content>
</entry>
</feed>
