{"id":767,"date":"2025-04-18T00:35:46","date_gmt":"2025-04-18T04:35:46","guid":{"rendered":"https:\/\/www.fitzsim.org\/blog\/?p=767"},"modified":"2025-04-18T00:35:46","modified_gmt":"2025-04-18T04:35:46","slug":"lisp-elf-toolkit","status":"publish","type":"post","link":"https:\/\/www.fitzsim.org\/blog\/?p=767","title":{"rendered":"Lisp ELF toolkit"},"content":{"rendered":"\n<p>I recently needed to generate an <code>ELF<\/code> binary with both <code>RPATH<\/code> and <code>RUNPATH<\/code> entries. I could not figure out how to produce this using linker command line arguments.<\/p>\n\n\n\n<p>I was considering attempting a linker script, but first I switched to my <code>Lisp<\/code> <code>REPL<\/code> buffer<sup> 1<\/sup> and found that <code>(ql:quickload \"elf\")<\/code> loaded a promising-looking <a href=\"https:\/\/github.com\/eschulte\/elf.git\"><code>Common Lisp ELF<\/code> library<\/a>.<\/p>\n\n\n\n<p>I created a stub library with <code>RPATH<\/code> using <code>gcc<\/code> and an empty <code>C<\/code> file, then loaded it with <code>(elf:read-elf)<\/code>.<\/p>\n\n\n\n<p>With the <code>SLIME<\/code> inspector (<code>M-x slime-inspect<\/code>) I could traverse the structure of the <code>ELF<\/code> headers. I eventually found the <code>RPATH<\/code> entry.<\/p>\n\n\n\n<p>In the <code>REPL<\/code> I built up a function to search for <code>RPATH<\/code> then <code>push<\/code> a new <code>RUNPATH<\/code> entry alongside it.<\/p>\n\n\n\n<p>It turned out the <code>ELF<\/code> library had no support for the <code>RUNPATH<\/code> entry, so I redefined its <code>dyn-tag<\/code> dictionary to include it.<\/p>\n\n\n\n<p>After adding <code>RUNPATH<\/code>, I wrote the modified <code>ELF<\/code> structures to a file using <code>(elf:write-elf)<\/code>. The generated <code>ELF<\/code> file sufficed for the test case.<\/p>\n\n\n\n<p>I thought this was an interesting use case to share, demonstrating unique properties of the <code>Lisp<\/code> environment. I published <a href=\"https:\/\/git.sr.ht\/~fitzsim\/add-runpath-to-rpath-elf\/tree\/d74f5e2d22a55242ed9b38aa583ed2ad8e61f5ac\/item\/add-runpath.lisp\">the result<\/a> (I realize now I should have written <code>generate-example-library.sh<\/code> in <code>Lisp<\/code> instead of shell!; oh well).<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Which I have been trying to keep open lately, inspired by <a href=\"https:\/\/funcall.blogspot.com\/2025\/04\/why-i-program-in-lisp.html\">this post<\/a>.<\/li><\/ol>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently needed to generate an ELF binary with both RPATH and RUNPATH entries. I could not figure out how to produce this using linker command line arguments. I was considering attempting a linker script, but first I switched to my Lisp REPL buffer 1 and found that (ql:quickload &#8220;elf&#8221;) loaded a promising-looking Common Lisp &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.fitzsim.org\/blog\/?p=767\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Lisp ELF toolkit&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-767","post","type-post","status-publish","format-standard","hentry","category-lisp","entry"],"_links":{"self":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/767","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=767"}],"version-history":[{"count":12,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/767\/revisions"}],"predecessor-version":[{"id":779,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/767\/revisions\/779"}],"wp:attachment":[{"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=767"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=767"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fitzsim.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=767"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}