PATCHELF(1)

πŸŽ€ patchelf(1) β€” Modify ELF files, bestie ✨

okay so this is the patchelf(1) page from the User Manuals, and it’s literally about modifying ELF files. Buckle up, bestie β€” it’s giving β€œsurgery for binaries” energy πŸ’–

🌸 NAME 🌸

patchelf β€” Modify ELF files

✨ SYNOPSIS ✨

patchelf OPTION FILE ...

πŸ¦‹ DESCRIPTION πŸ¦‹

PatchELF is literally a simple utility for modifying existing ELF executables and libraries. It can change the dynamic loader (β€œELF interpreter”) of executables, and it can change the RPATH of executables and libraries. That’s the whole vibe, no cap.

πŸ’… OPTIONS πŸ’…

okay so the single option you give operates on each FILE, editing in place. That’s the rule, bestie β€” periodt πŸ’–

Any option taking a string argument can also take a file by prefixing the argument with the @ symbol. See EXAMPLES for the cute little demo ✨

  • --page-size SIZE β€” Uses the given page size instead of the default. πŸ’…
  • --set-interpreter INTERPRETER β€” Change the dynamic loader (β€œELF interpreter”) of executable given to INTERPRETER. Slay.
  • --print-interpreter β€” Prints the ELF interpreter of the executable.
  • --print-os-abi β€” Prints the OS ABI of the executable (EI_OSABI field of an ELF file).
  • --set-os-abi ABI β€” Changes the OS ABI of the executable (EI_OSABI field of an ELF file). The ABI parameter is pretty flexible. For example, you can specify it as a "Linux", "linux", or even "lInUx" β€” all those names will set EI_OSABI field of the ELF header to the value "3", which corresponds to Linux OS ABI. The same applies to other ABI names β€” System V, FreeBSD, Solaris, etc. The ABI names are flexible like that ✨
  • --print-soname β€” Prints DT_SONAME entry of .dynamic section. Raises an error if DT_SONAME doesn't exist. 😭
  • --set-soname SONAME β€” Sets DT_SONAME entry of a library to SONAME.
  • --set-rpath RUNPATH β€” Change the DT_RUNPATH of the executable or library to RUNPATH.
  • --add-rpath RUNPATH β€” Add RUNPATH to the existing DT_RUNPATH of the executable or library.
  • --remove-rpath β€” Removes the DT_RPATH or DT_RUNPATH entry of the executable or library.
  • --shrink-rpath β€” Remove from the DT_RUNPATH or DT_RPATH all directories that do not contain a library referenced by DT_NEEDED fields of the executable or library.

For instance, if an executable references one library libfoo.so, has an RPATH "/lib:/usr/lib:/foo/lib", and libfoo.so can only be found in /foo/lib, then the new RPATH will be "/foo/lib". Clean that RPATH up, bestie ✨

  • --allowed-rpath-prefixes PREFIXES β€” Combined with the "--shrink-rpath" option, this can be used for further rpath tuning. For instance, if an executable has an RPATH "/tmp/build-foo/.libs:/foo/lib", it is probably desirable to keep the "/foo/lib" reference instead of the "/tmp" entry. Keep the good paths, bin the bad ones πŸ’…
  • --print-rpath β€” Prints the DT_RUNPATH or DT_RPATH for an executable or library.
  • --force-rpath β€” Forces the use of the obsolete DT_RPATH in the file instead of DT_RUNPATH. By default DT_RPATH is converted to DT_RUNPATH. Obsolete, bestie β€” respect the vintage πŸŽ€
  • --add-needed LIBRARY β€” Adds a declared dependency on a dynamic library (DT_NEEDED). This option can be given multiple times.
  • --replace-needed LIB_ORIG LIB_NEW β€” Replaces a declared dependency on a dynamic library with another one (DT_NEEDED). This option can be given multiple times.
  • --remove-needed LIBRARY β€” Removes a declared dependency on LIBRARY (DT_NEEDED entry). This option can be given multiple times.
  • --print-needed β€” Prints all DT_NEEDED entries of the executable.
  • --no-default-lib β€” Marks the object so that the search for dependencies of this object will ignore any default library search paths.
  • --build-resolution-cache β€” Resolves each DT_NEEDED dependency against the object's run path at patch time and records the result in a .note.nixos.ldcache note, so that a loader which understands the note can skip the run-path search at startup. Directories that cannot be resolved ahead of time (empty or relative components, those containing dynamic-string tokens such as $ORIGIN or a glibc-hwcaps subdirectory, and paths that cannot be searched at patch time because they are missing, not a directory, or not accessible) are stored as a search hint instead of an exact path. The cache is built once from an unpatched binary; this option cannot be combined with --force-rpath. 🚨
  • --no-sort β€” Do not sort program headers or section headers. This is useful when debugging patchelf, because it makes it easier to read diffs of the output of "readelf -a". Debugging vibe check: passed βœ… iykyk
  • --add-debug-tag β€” Adds DT_DEBUG tag to the .dynamic section if not yet present in an ELF object. A shared library (-shared) by default does not receive DT_DEBUG tag. This means that when a shared library has an entry point (so that it can be run as an executable), the debugger does not connect to it correctly and symbols are not resolved. 😭
  • --print-execstack β€” Prints the state of the executable flag of the GNU_STACK program header, if present.
  • --clear-execstack β€” Clears the executable flag of the GNU_STACK program header, or adds a new header.
  • --set-execstack β€” Sets the executable flag of the GNU_STACK program header, or adds a new header.
  • --rename-dynamic-symbols NAME_MAP_FILE β€” Renames dynamic symbols. The name map file should contain lines with the old and the new name separated by spaces like this:
old_name new_name

Symbol names do not contain version specifier that are also shown in the output of the nm -D command from binutils. So instead of the name write@GLIBC_2.2.5 it is just write. Iconic little rename glow-up ✨

  • --no-clobber-old-sections β€” Do not clobber old section values.

patchelf defaults to overwriting replaced header sections with garbage to ensure they are not used accidentally. This option allows to opt out of that behavior, so that binaries that attempt to read their own headers from a fixed offset (e.g. Firefox) continue working.

Use sparingly and with caution. 🚨

  • --output FILE β€” Set the output file name. If not specified, the input will be modified in place.
  • --debug β€” Prints details of the changes made to the input file.
  • --version β€” Shows the version of patchelf.

πŸ“ EXAMPLES πŸ“

To use the contents on an external file as a parameter, you literally do this:

$ patchelf a.out --add-rpath @/tmp/generated-rpath.bin

To change the RPATH of a binary, note that $ORIGIN is a special symbol used by the loader, so must be quoted. Yes, quoted, bestie β€” the loader is dramatic like that πŸ’…

patchelf --set-rpath '$ORIGIN/../lib64' a.out

πŸŽ€ AUTHOR πŸŽ€

Eelco Dolstra <e.dolstra@tudelft.nl>

🌈 SEE ALSO 🌈


And that’s the whole page, bestie! This is PATCHELF, dated JULY 2022, section 1 of the User Manuals β€” mwah πŸ’‹πŸŽ€βœ¨

πŸ“¦ where this page comes from