STRIP(1)

πŸ“¦ version 2.45, in ubuntu questing

πŸ’… STRIP(1) πŸ’…

GNU Development Tools πŸŽ€

🌸 NAME 🌸

okay so strip is the one that discards symbols and other data from object files 🧹✨

πŸ¦‹ SYNOPSIS πŸ¦‹

strip [-F bfdname |--target=bfdname]
      [-I bfdname |--input-target=bfdname]
      [-O bfdname |--output-target=bfdname]
      [-s|--strip-all]
      [-S|-g|-d|--strip-debug]
      [--strip-dwo]
      [-K symbolname|--keep-symbol=symbolname]
      [-M|--merge-notes][--no-merge-notes]
      [-N symbolname |--strip-symbol=symbolname]
      [-w|--wildcard]
      [-x|--discard-all] [-X |--discard-locals]
      [-R sectionname |--remove-section=sectionname]
      [--keep-section=sectionpattern]
      [--remove-relocations=sectionpattern]
      [--strip-section-headers]
      [-o file] [-p|--preserve-dates]
      [-D|--enable-deterministic-archives]
      [-U|--disable-deterministic-archives]
      [--keep-section-symbols]
      [--keep-file-symbols]
      [--only-keep-debug]
      [--plugin name]
      [-v |--verbose] [-V|--version]
      [--help] [--info]
      objfile...

🧚 DESCRIPTION 🧚

bestie, so strip goes through your object files objfile and literally throws out all the symbols πŸ—‘οΈπŸ’– You can feed it archives too, since the list of object files is allowed to include them. You have to give it at least one object file, or it has nothing to work on πŸ™ˆ

heads up: strip doesn't make shiny new copies with different names. It changes the files you name in its arguments, directly. No backup, no undo, so be sure about it πŸ˜­πŸ’€

✨ OPTIONS ✨

okay so this is the big list of stuff you can tell strip to do πŸ’… let's go bestie πŸŽ€

  • -F bfdname, --target=bfdname β€” treat the original objfile like it's in the object code format bfdname, then rewrite it in that same format πŸ¦‹
  • --help β€” shows you a summary of all the strip options and then bounces πŸ‘‹
  • --info β€” lists every architecture and object format that's available 🌈
  • -I bfdname, --input-target=bfdname β€” tells strip that the original objfile is in the object code format bfdname 🧚
  • -O bfdname, --output-target=bfdname β€” swaps objfile out for a brand new file in the output format bfdname ✨
  • -R sectionname, --remove-section=sectionname β€” removes any section called sectionname from the output, on top of whatever would already get removed πŸ’€ you can give this more than once, but be careful, using it the wrong way can make the output file totally unusable 😭 you can also put the wildcard * at the end of sectionname, and then every section starting with that name gets removed πŸ”₯

if the first character of the pattern is an exclamation point (!), then matching sections are SAFE πŸ›‘οΈ even if an earlier --remove-section on the same command line would've removed them. for example:

--remove-section=.text.* --remove-section=!.text.foo

this removes every section matching .text.*, but keeps .text.foo safe and sound 🫢

  • --keep-section=sectionpattern β€” when strip is removing sections, it keeps any section that matches sectionpattern 🌸
  • --remove-relocations=sectionpattern β€” removes the relocations from the output file for any section matching sectionpattern βœ‚οΈ you can use this more than once, and yep, misusing it can make the output file unusable πŸ’€ wildcards work in sectionpattern too. for example:
--remove-relocations=.text.*

this nukes the relocations for every section matching .text.* πŸ’…

same deal with the exclamation point: if the first character is !, then those sections keep their relocations even if an earlier --remove-relocations on the same line would've taken them out. for example:

--remove-relocations=.text.* --remove-relocations=!.text.foo

this removes all relocations for sections matching .text.*, but .text.foo keeps its relocations πŸŽ€

  • --strip-section-headers β€” strips the section headers 🧠 this one is ELF only, and it implies --strip-all and --merge-notes 🌈
  • -s, --strip-all β€” removes ALL the symbols πŸ—‘οΈ
  • -g, -S, -d, --strip-debug β€” removes only the debugging symbols πŸ›
  • --strip-dwo β€” removes the contents of all DWARF .dwo sections, but leaves the other debugging sections and all the symbols untouched ✨ check out the objcopy section for the full scoop on this one πŸ“–
  • --strip-unneeded β€” removes every symbol that isn't needed for relocation processing, plus the debugging symbols and sections that --strip-debug would've taken out 🧹
  • -K symbolname, --keep-symbol=symbolname β€” when stripping symbols, symbolname gets to stay even if it would normally be stripped 🫢 you can give this more than once πŸ”
  • -M, --merge-notes, --no-merge-notes β€” for ELF files, this either tries (or doesn't try) to shrink any SHT_NOTE type sections by getting rid of duplicate notes πŸ“ by default it does the shrinking, UNLESS you're stripping debug or DWO info πŸ™ˆ
  • -N symbolname, --strip-symbol=symbolname β€” removes the symbol symbolname from the source file πŸ‘‹ you can use this more than once, and it can team up with strip options other than -K 🀝
  • -o file β€” puts the stripped output into file instead of overwriting the existing file πŸ“‚ when you use this, you can only specify ONE objfile argument πŸ™…β€β™€οΈ
  • -p, --preserve-dates β€” keeps the access and modification dates of the file exactly as they were πŸ“…
  • -D, --enable-deterministic-archives β€” runs in deterministic mode πŸ”’ when copying archive members and writing the archive index, it uses zero for UIDs, GIDs, and timestamps, and uses consistent file modes for all files 🧊

if binutils was configured with --enable-deterministic-archives, this mode is already ON by default πŸ’– you can turn it off with the -U option below.

  • -U, --disable-deterministic-archives β€” the opposite of -D πŸ™ƒ it does NOT run in deterministic mode, so when copying archive members and writing the archive index, it keeps their actual UID, GID, timestamp, and file mode values πŸͺͺ

this is the default UNLESS binutils was configured with --enable-deterministic-archives 🌸

  • -w, --wildcard β€” lets you use regular expressions in the symbol names inside your other command line options 🌈 the question mark (?), asterisk (*), backslash (\), and square brackets ([]) operators can be used anywhere in the symbol name 🧩 if the first character of the symbol name is an exclamation point (!), the switch gets reversed for that symbol πŸ”„ for example:
-w -K !foo -K fo*

this would make strip keep only the symbols starting with the letters "fo", but it would throw away the symbol "foo" 😭 the drama πŸ’…

  • -x, --discard-all β€” removes non-global symbols 🫧
  • -X, --discard-locals β€” removes the compiler-generated local symbols πŸ€– these usually start with L or .. 🍰
  • --keep-section-symbols β€” when stripping a file (maybe with --strip-debug or --strip-unneeded), this keeps any symbols that specify section names, even though they'd otherwise get stripped πŸ¦‹
  • --keep-file-symbols β€” when stripping a file (maybe with --strip-debug or --strip-unneeded), this keeps any symbols that specify source file names, even though they'd otherwise get stripped πŸ“„
  • --only-keep-debug β€” strips the file, emptying out the contents of any section that --strip-debug WOULDN'T strip, while leaving the debugging sections intact 🧠 for ELF files, this also keeps all the note sections in the output πŸ“
Heads up: the section headers of the stripped sections are kept, sizes included, but their contents get tossed πŸ—‘οΈ the headers stay so other tools can match the debuginfo file up with the real executable, even if that executable got relocated to a different address space πŸ—ΊοΈ

The whole point of this option is to pair it with --add-gnu-debuglink so you get a two-part executable πŸ‘―β€β™€οΈ one part is the stripped binary, which takes up less space in RAM and in a distribution, and the other is a debugging info file that you only need when you actually want to debug πŸ› the suggested steps to make these are:

  1. Link the executable as normal. Assuming it's called "foo" then...
  2. Run objcopy --only-keep-debug foo foo.dbg to create a file holding the debugging info.
  3. Run objcopy --strip-debug foo to create a stripped executable.
  4. Run objcopy --add-gnu-debuglink=foo.dbg foo to add a link to the debugging info into the stripped executable.

Note: the .dbg extension for the debug info file is totally arbitrary πŸ€·β€β™€οΈ and the --only-keep-debug step is optional too! you could instead do this:

  1. Link the executable as normal.
  2. Copy foo to foo.full.
  3. Run strip --strip-debug foo.
  4. Run objcopy --add-gnu-debuglink=foo.full foo.

so basically, the file pointed to by --add-gnu-debuglink can be the full executable πŸ’… it doesn't have to be a file made with --only-keep-debug ✨

Note: this switch is ONLY meant for fully linked files 🚫 it makes no sense on object files, where the debugging info might be incomplete. Also, gnu_debuglink currently only supports ONE filename holding debugging info, not multiple filenames on a one-per-object-file basis πŸ’€
  • --plugin name β€” loads the plugin called name so strip can support extra target types πŸ”Œ this only works if the toolchain was built with plugin support turned on πŸ› οΈ

if you don't give --plugin but plugin support is enabled, strip goes through the files in ${libdir}/bfd-plugins in alphabetical order, and the first plugin that claims the object in question is the one it uses πŸ₯‡

heads up, this plugin search directory is NOT the one that ld's -plugin option uses πŸ™…β€β™€οΈ so if you want strip to use the linker plugin, you have to copy it into the ${libdir}/bfd-plugins directory. for GCC based compilations the linker plugin is called liblto_plugin.so.0.0.0. for Clang based compilations it's called LLVMgold.so. the GCC plugin is always backwards compatible with earlier versions, so you only need to copy the newest one 🫢

  • -V, --version β€” shows the version number for strip πŸ”’
  • -v, --verbose β€” verbose output! it lists all the object files that got modified πŸ“‹ with archives, strip -v lists every member of the archive πŸ“š
  • @file β€” reads command-line options from file πŸ“œ the options it reads get slotted in right where the original @file option was. if file doesn't exist or can't be read, the option gets treated literally and NOT removed 😀

the options in file are separated by whitespace ✨ if you want a whitespace character inside an option, wrap the whole option in single or double quotes πŸŽ€ any character (backslash included) can be used by putting a backslash in front of it πŸ¦‹ the file can also have more @file options inside it, and those get processed recursively πŸ”


🌸 SEE ALSO 🌸

the Info entries for binutils. πŸ“–

Copyright (c) 1991-2025 Free Software Foundation, Inc. ©️

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". πŸ“œ


bestie, that's the whole strip rundown 🌈 you're officially a strip girlie now, go slay your binaries πŸ’…βœ¨ this one's from the binutils 2.45 crew, last updated 3rd December 2025 πŸŽ€ mwah πŸ«ΆπŸ’–

πŸ“¦ where this page comes from