<div dir="ltr"><div>Recently LLD made it to the front page of HN (yay!): <a href="https://news.ycombinator.com/item?id=13670458" target="_blank">https://news.ycombinator.com/<wbr>item?id=13670458</a><br></div><div>This comment about the Solaris linker surprised me: <a href="https://news.ycombinator.com/item?id=13672364" target="_blank">https://news.ycombinator.<wbr>com/item?id=13672364</a></div><div><br></div><div>"""</div><div>> To me, the biggest advantage is cross compiling</div><div><br></div><div>Not all system linkers have this problem. For example, Solaris ld(1) is perfectly capable of cross-linking any valid ELF file.</div><div>"""</div><div><br></div><div>This got me interested in looking at what the solaris linker was like.</div><div>I had known that Solaris had done quite a few innovations in the linker space, but I had never actually looked at their iinker (the time I spent interacting with Solaris/illumos was related to DTrace stuff and happened before I started working on linkers).</div><div><br></div><div><br></div><div><br></div><div>The basic layout seems to be:</div><div><a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/ld/common/ld.c" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/ld/common/ld.c</a><br></div><div>This is where `main` is.</div><div><br></div><div>The actual linker has a "main in a library" type interface that is called into from main() by:</div><div><br></div><div><div>718<span class="m_820910608402612148gmail-Apple-tab-span" style="white-space:pre-wrap">      </span>/* Call the libld entry point for the specified ELFCLASS */</div><div>719<span class="m_820910608402612148gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>if (class == ELFCLASS64)</div><div>720<span class="m_820910608402612148gmail-Apple-tab-span" style="white-space:pre-wrap">           </span>return (ld64_main(argc, argv, mach));</div><div>721<span class="m_820910608402612148gmail-Apple-tab-span" style="white-space:pre-wrap">      </span>else</div><div>722<span class="m_820910608402612148gmail-Apple-tab-span" style="white-space:pre-wrap">               </span>return (ld32_main(argc, argv, mach));</div></div><div><br></div><div><br></div><div>The rest of the code is in "libld". The header is here:</div><div><a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/include/libld.h" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/include/libld.h</a><br></div><div><br></div><div>There seems to be a huge "context" struct `struct ofl_desc`: <a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/include/libld.h#241" target="_blank">http://src.illumos.<wbr>org/source/xref/illumos-gate/<wbr>usr/src/cmd/sgs/include/libld.<wbr>h#241</a></div><div>(it does have a couple globals in <a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libld/common/globals.c" target="_blank">http://src.illumos.org/<wbr>source/xref/illumos-gate/usr/<wbr>src/cmd/sgs/libld/common/<wbr>globals.c</a></div><div>And also the "Target" struct is a global apparently: <a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libld/common/_libld.h#47" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/libld/common/_libld.h#47</a></div><div>)</div><div><br></div><div>The code itself is mostly here:</div><div><a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libld/common/" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/libld/common/</a><br></div><div><br></div><div>The libld "main" function seems to be in:</div><div><a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libld/common/ldmain.c#144" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/libld/common/ldmain.c#144</a><br></div><div><br></div><div>The function that handles individual sections in object files is `process_elf` in:</div><div><a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libld/common/files.c#2525" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/libld/common/files.c#2525</a><br></div><div><br></div><div><div><a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libld/common/README.XLINK" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/libld/common/README.XLINK</a></div></div><div><br></div><div>(one interesting thing is that besides being used for the regular `ld` command line program, libld.so is also used implicitly if you try to dlopen a relocatable object (which is a bit weird))</div><div><br></div><div><br></div><div><br></div><div>I haven't traced through all of it yet. Has anybody stared at this code? How does it compare architecturally with LLD? If you're looking through for the first time, please post any findings/insights in this thread so others can follow along.</div><div><br></div><div>(for the record, `illumos-gate/usr/src/cmd/sgs/<wbr>libld/common % wc -l *.c` gives about 45k lines of code, so LLD/ELF is still quite a bit slimmer, though giving solaris libld a factor of 2 handicap due to using C vs C++ brings them basically to parity)</div><div><br></div><div><br></div><div><br></div><div><br></div><div>There even seems to be a simple "libelf": <a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libelf/common/" target="_blank">http://src.illumos.<wbr>org/source/xref/illumos-gate/<wbr>usr/src/cmd/sgs/libelf/common/</a></div><div>Main interface is the "struct Elf": <a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libelf/common/decl.h#270" target="_blank">http://src.illumos.org/source/<wbr>xref/illumos-gate/usr/src/cmd/<wbr>sgs/libelf/common/decl.h#270</a></div><div>`struct Elf` also handles archives.</div><div><br></div><div>It seems to be roughly libobject-like, though it seems to support writing.</div><div>There are some "demos" here: <a href="http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sgs/libelf/demo/" target="_blank">http://src.illumos.org/<wbr>source/xref/illumos-gate/usr/<wbr>src/cmd/sgs/libelf/demo/</a> (note the README)</div><div><br></div><div>It seems like it tries to paper over the fact that writing can cause it to have to do O(the entire file) work if it needs to slide sections around / fixup offsets (haven't looked super closely though). E.g. it seems to try to transparently handle the case where you append extra data to a section. It doesn't seem to handle "symbols" explicitly (just exposes the raw section data), so it doesn't need to worry about operations like "convert a local symbol to weak" which requires rewriting all sorts of stuff.</div><div><br></div><div><br></div><div>-- Sean Silva</div><div><br></div><div><br></div><div><br></div></div>