Home / Alt manpages / elfedit(1)

  • elfedit(1)
  • User command
  • linux

Safely Change ELF Metadata with elfedit

You will finish with a repeatable way to change selected ELF header fields, verify the result with readelf, and restore the original file if the change is wrong. The examples use GNU Binutils 2.42, which is the version installed here.

Allow about fifteen minutes. You need elfedit, readelf, a shell, and an ELF file that you are allowed to modify. The commands normally need no elevated privileges. Use sudo only when the file's ownership or permissions genuinely require it; root access does not make an unsafe metadata change safe.

Warning

elfedit edits files in place. Work on a copy first, keep a backup until verification is complete, and do not experiment on a running system binary or a production service executable.

1. Check the installed command

Confirm which binary will run and record its version:

$ command -v elfedit
/usr/bin/elfedit
$ elfedit --version
GNU elfedit (GNU Binutils for Ubuntu) 2.42

The installed elfedit, aarch64-linux-gnu-elfedit, and x86_64-linux-gnu-elfedit manpages describe the same Binutils 2.42 interface. The target-prefixed names do not make it safe to assume that every target-specific machine name is accepted. This build documents i386, IAMCU, L1OM, K1OM, and x86-64 for machine matching and output.

Checkpoint: if elfedit --version reports a different release, read that installation's manual before copying the examples. Option names and supported values are version-specific.

2. Make a disposable working copy

Choose an ELF file and copy it to a temporary or working directory. This example uses the harmless system utility true; replace the source with your own file:

$ mkdir -p "$HOME/elfedit-work"
$ cp /usr/bin/true "$HOME/elfedit-work/true"
$ cp "$HOME/elfedit-work/true" "$HOME/elfedit-work/true.orig"
$ file "$HOME/elfedit-work/true"
/home/you/elfedit-work/true: ELF 64-bit LSB pie executable, ...

The second copy is the undo path. Keep it unchanged. If you are editing an archive containing ELF files, make a separate archive backup as well: the manual says archives are supported, but an archive edit is still a write operation.

3. Inspect the original header

Use readelf before changing anything. The header fields relevant to this guide are class, file type, machine, OSABI, and ABI version:

$ readelf -h "$HOME/elfedit-work/true" | grep -E 'Class:|OS/ABI:|Type:|Machine:|ABI Version:'
  Class:                             ELF64
  OS/ABI:                            UNIX - System V
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  ABI Version:                       0

The exact machine description and spacing vary. Save the important values, not the presentation. The original file here is a 64-bit position-independent executable, so changing its file type or machine field would be much more consequential than changing a test OSABI value.

4. Change selected header fields

At least one output option is required. This example changes the copied file's OSABI to the installed command's Linux alias for GNU and sets the ELF ABI version to 7:

$ elfedit \
    --output-osabi=Linux \
    --output-abiversion=7 \
    "$HOME/elfedit-work/true"
$ readelf -h "$HOME/elfedit-work/true" | grep -E 'OS/ABI:|ABI Version:'
  OS/ABI:                            UNIX - GNU
  ABI Version:                       7

Other output fields are --output-mach and --output-type. The supported file types in this installation are rel, exec, and dyn. OSABI values include none, GNU, Linux, FreeBSD, and others listed by elfedit --help. ABI versions must be integers from 0 through 255.

Safety boundary

Changing the machine or file type can make a file unusable, even if the command exits successfully. Do not use those options to force a loader or build tool to accept an incompatible file. Test the result with the real consumer, and keep the backup until that test has passed.

5. Add an input filter before a risky edit

Input options make the edit conditional. For example, this command changes only a relocatable object whose machine is x86-64:

$ elfedit \
    --input-mach=x86-64 \
    --input-type=rel \
    --output-osabi=GNU \
    path/to/object.o

If the file does not match, elfedit reports an unmatched field and returns a non-zero status. In a local test, applying --input-type=rel to an ordinary PIE produced Unmatched e_type, status 1, and left the OSABI unchanged. Treat a non-zero status as a failed edit and inspect the file again instead of continuing automatically.

The other filters are --input-osabi and --input-abiversion. Omitting an input filter means that field matches any value. That is convenient for a controlled copy, but it is a poor guardrail for a script processing files from several build stages.

6. Use a response file when the command is long

Options can be read from an @file. Put one or more whitespace-separated options in the file, quoting an option when its value needs whitespace:

$ printf '%s\n' '--output-osabi=NetBSD' > "$HOME/elfedit-work/options.txt"
$ cp "$HOME/elfedit-work/true.orig" "$HOME/elfedit-work/response-test"
$ elfedit "@$HOME/elfedit-work/options.txt" "$HOME/elfedit-work/response-test"
$ readelf -h "$HOME/elfedit-work/response-test" | grep 'OS/ABI:'
  OS/ABI:                            UNIX - NetBSD

Response files may include other response files recursively. A missing or unreadable file is treated literally, so check the exit status and inspect the result. Do not build a response file from untrusted text without controlling its contents.

7. Verify, recover, and automate carefully

Verification is a separate step. Re-run readelf -h and compare every field you intended to change. For a script, capture the status immediately and stop on failure:

$ elfedit --output-osabi=Linux --output-abiversion=7 "$HOME/elfedit-work/true"
$ status=$?
$ if [ "$status" -ne 0 ]; then
>     printf 'elfedit failed with status %s\n' "$status" >&2
>     exit "$status"
> fi
$ readelf -h "$HOME/elfedit-work/true" | grep -E 'OS/ABI:|ABI Version:'

To undo the examples, replace the changed copy with the untouched backup:

$ cp "$HOME/elfedit-work/true.orig" "$HOME/elfedit-work/true"
$ readelf -h "$HOME/elfedit-work/true" | grep -E 'OS/ABI:|ABI Version:'
  OS/ABI:                            UNIX - System V
  ABI Version:                       0

This recovery works because the example preserved a byte-for-byte original. If you edited the only copy, recovery depends on your normal backup system. Do not assume that changing the header back will restore padding, archive metadata, or other bytes changed by a failed or interrupted operation.

Done means

  • You confirmed the installed Binutils version and supported option values.
  • You copied the ELF file and retained an untouched backup.
  • You inspected the original header before editing it.
  • You used an input filter where the edit needed a precise precondition.
  • You checked the exit status and verified the changed fields with readelf.
  • You know the restore command and have not modified a production executable by accident.