LLVM-IFS(1)

LLVM-IFS ๐Ÿ’…

okay bestie, welcome to llvm-ifs โ€” the shared object stubbing tool. yes it's from the LLVM manual, yes it's a whole vibe, and yes you're gonna understand it. let's go ๐Ÿฆ‹


โœจ SYNOPSIS โœจ

llvm-ifs [options] inputs

๐Ÿ’– DESCRIPTION ๐Ÿ’–

so. llvm-ifs is that girl who does two jobs at once, and she does both flawlessly. she jointly produces human readable text-based stubs (the .ifs files) for shared objects, AND linkable shared object stubs (the .so files) โ€” and she can build them from either ELF shared objects or text-based stubs. no cap.

why do you care? two reasons, and they're both iconic:

  • the text-based stubs are literally perfect for monitoring ABI changes of the shared object ๐Ÿ‘€
  • the linkable shared object stubs let you avoid unnecessary relinks when the ABI of shared libraries doesn't change โ€” so your build stops doing cardio for no reason ๐Ÿƒโ™€๏ธ๐Ÿ’จ

๐ŸŽ€ IFS FORMATS ๐ŸŽ€

here's what the text representation (IFS) of a shared object looks like when llvm-ifs makes one. it's giving โœจstructuredโœจ:

--- !ifs-v1
IFSVersion: 3.0
SoName: libtest.so /* Optional */
Target: x86_64-unknown-linux-gnu   /* Optional, format 1, same format as llvm target triple */
Target: { Arch: x86_64, Endianness: little, Bitwidth: 64 } /* Optional, format 2 */
NeededLibs:
  - libc.so.6
Symbols:
  - { Name: sym0, Type: Notype }
  - { Name: sym1, Type: Object, Size: 0 }
  - { Name: sym2, Type: Func, Weak: false }
  - { Name: sym3, Type: TLS }
  - { Name: sym4, Type: Unknown, Warning: foo }
...

now let's decode every single field, bestie, because they all matter:

  • IFSVersion โ€” the version of the IFS file, for reader compatibility. it's the handshake. ๐Ÿค
  • SoName (optional) โ€” the name of the shared object file that's being stubbed.
  • Target (optional) โ€” the architecture, endianness and bitwise information of this shared object. it can be in explicit format or in implicit LLVM triple format. it can be optional, and it can be overridden from command line options.
  • NeededLibs โ€” the list of external shared objects that this library depends on. her little support system ๐Ÿซถ
  • Symbols โ€” a collection of all data needed to link objects for each symbol, sorted by name in ascending order. yes, sorted. we love an organized queen.
    • Name โ€” symbol name.
    • Type โ€” whether the symbol is an object, function, no-type, thread local storage, or unknown. symbol types that aren't explicitly supported get mapped as unknown to improve the signal-to-noise ratio (iconic behaviour tbh).
    • Size โ€” the size of the symbol in question. doesn't apply to functions, and it's optional for NoType symbols.
    • Undefined โ€” whether or not the symbol is defined in this shared object file.
    • Weak โ€” whether or not the symbol should be treated as weak. ๐Ÿฅบ
    • Warning (optional) โ€” warning text to output when this symbol is linked against.

this YAML based text format contains everything that's needed to generate a linkable ELF shared object as well as an Apple TAPI format file. the ordering of symbols is sorted, so these files can be easily compared using diff tools. and here's the tea: if the content of the file changes, it indicates a potentially ABI breaking change. ๐Ÿšจ


๐ŸŒˆ ELF STUB FORMAT ๐ŸŒˆ

a minimum ELF file that can be used by a linker should have these sections properly populated, no skips:

  • ELF header.
  • Section headers.
  • Dynamic symbol table (โ€‹.dynsym section).
  • Dynamic string table (โ€‹.dynstr section).
  • Dynamic table (โ€‹.dynamic section).
    • DT_SYMTAB entry.
    • DT_STRTAB entry.
    • DT_STRSZ entry.
    • DT_NEEDED entries. (optional)
    • DT_SONAME entry. (optional)
  • Section header string table (โ€‹.shstrtab section)
heads up bestie: this ELF file may have compatibility issues with ELF analysis tools that rely on the program headers. but linkers like LLD work fine with such a minimum ELF file, no errors, no drama. ๐Ÿ’…

โญ OPTIONS โญ

  • --input-format=[IFS|ELF|OtherObjectFileFormats] โ€” specify the input file format. currently, only text IFS files and ELF shared object files are supported. this flag is optional because the input format can be inferred. she reads the room. ๐Ÿ”ฎ
  • --output-elf=<output-filename> โ€” specify the output file for the ELF shared object stub.
  • --output-ifs=<output-filename> โ€” specify the output file for the text IFS.
  • --output-tbd=<output-filename> โ€” specify the output file for the Apple TAPI tbd.
  • --arch=[x86_64|AArch64|...] โ€” optional, and it should only be used when reading an IFS file that doesn't define the Arch (architecture). this flag defines the architecture of the output file, and it can be any string supported by the ELF e_machine field. if the value is conflicting with the IFS file, an error will be reported and the program will stop.
  • --endianness=[little|big] โ€” optional, and it should only be used when reading an IFS file that doesn't define the Endianness. this flag defines the endianness of the output file. if the value is conflicting with the IFS file, an error will be reported and the program will stop.
  • --bitwidth=[32|64] โ€” optional, and it should only be used when reading an IFS file that doesn't define the BitWidth. this flag defines the bit width of the output file. if the value is conflicting with the input IFS file, an error will be reported and the program will stop.
  • --target=<target triple> โ€” optional, and it should only be used when reading an IFS file that doesn't define any target information. this flag defines the architecture, endianness and bit width of the output file using an LLVM target triple. this flag cannot be used simultaneously with other target related flags. pick a lane bestie ๐Ÿšซ
  • --hint-ifs-target=<target triple> โ€” optional, and it should only be used when reading an ELF shared object and generating an IFS file. by default, llvm-ifs will use the Arch, Endianness and BitWidth fields to reflect the target information from the input object file. using this flag tells llvm-ifs the expected target triple in the output IFS file. if the value matches the target information from the object file, this value gets used in the Target: field in the generated IFS. if it conflicts with the input object file, an error will be reported and the program will stop.
  • --hint-ifs-target โ€” optional, and it should only be used when outputting an IFS file. this flag strips the Arch field from the IFS file so it can be overridden later. โœ‚๏ธ
  • --strip-ifs-endianness โ€” optional, and it should only be used when outputting an IFS file. this flag strips the Endianness field from the IFS file so it can be overridden later.
  • --strip-ifs-bitwidth โ€” optional, and it should only be used when outputting an IFS file. this flag strips the BitWidth field from the IFS file so it can be overridden later.
  • --strip-ifs-target โ€” optional, and it should only be used when outputting an IFS file. this flag strips the Target field from the IFS file so it can be overridden later.
  • --write-if-changed โ€” when this flag is set, llvm-ifs will only write the output file if it doesn't already exist, or if the content would be different from the existing file. no unnecessary writes, we're eco-friendly here ๐ŸŒฑ
  • --strip-size โ€” when this flag is set, llvm-ifs will remove the size field from the output IFS file. this is useful for shared objects that only intend to be linked against position independent code, which doesn't need copy relocations, or where the size of an object isn't a useful part of the ABI to track. ๐Ÿ“โœ‚๏ธ

๐Ÿ’€ EXIT STATUS ๐Ÿ’€

if llvm-ifs succeeds, she exits with 0. otherwise, if an error occurs, she exits with a non-zero value. simple as that.


๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

maintained by the LLVM Team (https://llvm.org/). periodt. ๐Ÿ’…


2003-2025, LLVM Project


and that's the whole page, bestie!! ๐Ÿฆ‹โœจ this was LLVM release 20, dated 2025-09-03 โ€” go forth and stub your shared objects responsibly, mwah ๐Ÿ’–๐ŸŽ€

๐Ÿ“ฆ where this page comes from