After having been limited to maintenance for a while I finally got around to some feature work on ELF Dissector again this week, another side-project of mine I haven’t written about here yet. ELF Dissector is an inspection tool for the internals of ELF files, the file format used for executables and shared libraries on Linux and a few other operating systems.

Use Cases

As a quick introduction, let’s focus on what ELF Dissector is most useful for.

  • Inspecting forward and backward dependencies, on library and symbol level. Say you want to remove the dependency on a legacy library like KDELibs4Support from your application, the inverse dependency viewer helps you to identify what exactly pulls in this library, and which symbols are used from it.
  • Identifying load-time performance bottlenecks such as expensive static constructors or excessive relocations. An example for this is David Edmundson’s current research into KInit.
  • Size profiling of ELF files. That’s easiest shown in the picture below.
ELF Dissector visualizing size cost using a tree map.
ELF Dissector size tree map view.

AArch64 Support

Last week I had to analyze 64bit ARM binaries with ELF Dissector for the first time, which made me run into an old limitation of ELF Dissector’s disassembler. Until now ELF Dissector used Binutils for this (via some semi-public API), which works very well but unfortunately only on the host platform (that is, usually for x86 code). So this limitation finally needed to go.

We now have support for using the cross-platform disassembler framework Capstone. So far only AArch64 and x86 support are actually implemented, but adding further architectures is now quite straightforward. Together with a few other fixes and improvements, such as support for relocations in the .init_array section, ELF Dissector is now actually useful for inspecting loading performance of Aarch64 binaries too.

ELF Dissector showing AArch64 assembler.
ELF Dissector showing AArch64 assembler.

Outlook

ELF Dissector had its first commit more than six years ago, but it is still lingering around in a playground repository, which doesn’t really do it justice. One major blocker for making it painlessly distributable however are its dependencies on private Binutils/GCC API. Using the Capstone disassembler is therefore also a big step towards addressing that, now only the use of the demangler API remains.