OBJCOPY(1)
π objcopy π
objcopy is part of the GNU Development Tools crew, and it is iconic for copying and translating object files π β¨
π NAME
objcopy - copy and translate object files π¦
πΈ SYNOPSIS
objcopy [-F bfdname|--target=bfdname]
[-I bfdname|--input-target=bfdname]
[-O bfdname|--output-target=bfdname]
[-B bfdarch|--binary-architecture=bfdarch]
[-S|--strip-all]
[-g|--strip-debug]
[--strip-unneeded]
[-K symbolname|--keep-symbol=symbolname]
[--keep-file-symbols]
[--keep-section-symbols]
[-N symbolname|--strip-symbol=symbolname]
[--strip-unneeded-symbol=symbolname]
[-G symbolname|--keep-global-symbol=symbolname]
[--localize-hidden]
[-L symbolname|--localize-symbol=symbolname]
[--globalize-symbol=symbolname]
[--globalize-symbols=filename]
[-W symbolname|--weaken-symbol=symbolname]
[-w|--wildcard]
[-x|--discard-all]
[-X|--discard-locals]
[-b byte|--byte=byte]
[-i [breadth]|--interleave[=breadth]]
[--interleave-width=width]
[-j sectionpattern|--only-section=sectionpattern]
[-R sectionpattern|--remove-section=sectionpattern]
[--keep-section=sectionpattern]
[--remove-relocations=sectionpattern]
[--strip-section-headers]
[-p|--preserve-dates]
[-D|--enable-deterministic-archives]
[-U|--disable-deterministic-archives]
[--debugging]
[--gap-fill=val]
[--pad-to=address]
[--set-start=val]
[--adjust-start=incr]
[--change-addresses=incr]
[--change-section-address sectionpattern{=,+,-}val]
[--change-section-lma sectionpattern{=,+,-}val]
[--change-section-vma sectionpattern{=,+,-}val]
[--change-warnings] [--no-change-warnings]
[--set-section-flags sectionpattern=flags]
[--set-section-alignment sectionpattern=align]
[--add-section sectionname=filename]
[--dump-section sectionname=filename]
[--update-section sectionname=filename]
[--rename-section oldname=newname[,flags]]
[--long-section-names {enable,disable,keep}]
[--change-leading-char] [--remove-leading-char]
[--reverse-bytes=num]
[--srec-len=ival] [--srec-forceS3]
[--redefine-sym old=new]
[--redefine-syms=filename]
[--weaken]
[--keep-symbols=filename]
[--strip-symbols=filename]
[--strip-unneeded-symbols=filename]
[--keep-global-symbols=filename]
[--localize-symbols=filename]
[--weaken-symbols=filename]
[--add-symbol name=[section:]value[,flags]]
[--alt-machine-code=index]
[--prefix-symbols=string]
[--prefix-sections=string]
[--prefix-alloc-sections=string]
[--add-gnu-debuglink=path-to-file]
[--only-keep-debug]
[--strip-dwo]
[--extract-dwo]
[--extract-symbol]
[--writable-text]
[--readonly-text]
[--pure]
[--impure]
[--file-alignment=num]
[--heap=reserve[,commit]]
[--image-base=address]
[--section-alignment=num]
[--stack=reserve[,commit]]
[--subsystem=which:major.minor]
[--compress-debug-sections]
[--decompress-debug-sections]
[--elf-stt-common=val]
[--merge-notes]
[--no-merge-notes]
[--verilog-data-width=val]
[-v|--verbose]
[-V|--version]
[--help] [--info]
infile [outfile]
π DESCRIPTION
okay so, the GNU objcopy utility copies the contents of one object file into another π«Ά It uses the GNU BFD Library to read and write the object files, and the destination file can be in a different format from the source. How it behaves is controlled entirely by your command-line options. Also, objcopy should be able to copy a fully linked file between any two formats, but copying a relocatable object file between any two formats may not work as expected π
objcopy makes temporary files to do its translations and deletes them afterward β¨ It does all of its translation work with BFD, so it can access every format described in BFD and is able to recognize most formats without you having to tell it explicitly. main character energy π
You can use objcopy to generate S-records by setting an output target of srec (for example, -O srec) π§
You can also generate a raw binary file by setting an output target of binary (for example, -O binary) π When objcopy makes a raw binary file, it basically produces a memory dump of the contents of the input object file. All symbols and relocation information get discarded. The memory dump starts at the load address of the lowest section copied into the output file.
When you're generating an S-record or a raw binary file, it can be super helpful to use-Sto remove sections holding debugging information. In some cases-Ris useful for removing sections that hold info the binary file doesn't need π
Note---objcopyis not able to change the endianness of its input files. If the input format has an endianness (some formats don't),objcopycan only copy the inputs into file formats with the same endianness or with no endianness at all (for example,srec). (However, see the--reverse-bytesoption.) π
β¨ OPTIONS β¨
infile,outfileβ These are the input and output files, respectively. If you don't specifyoutfile,objcopymakes a temporary file and destructively renames the result to the name ofinfileπ«£-I bfdname,--input-target=bfdnameβ Treat the source file's object format asbfdnameinstead of trying to figure it out on its own π-O bfdname,--output-target=bfdnameβ Write the output file in thebfdnameobject format π-F bfdname,--target=bfdnameβ Usebfdnameas the object format for both the input and output file. Basically, the data just gets transferred from source to destination with no translation π¦-B bfdarch,--binary-architecture=bfdarchβ This is handy when you're turning an architecture-less input file into an object file. In that case, the output architecture can be set tobfdarch. This option gets ignored if the input file has a knownbfdarch. You can reach this binary data from inside a program by referencing the special symbols that get created during the conversion:_binary_objfile_start,_binary_objfile_endand_binary_objfile_size. For example, you can turn a picture file into an object file and then access it in your code through those symbols πΌοΈβ¨-j sectionpattern,--only-section=sectionpatternβ Copy only the sections you name from the input file to the output file. You can give this option more than once. Be careful, because using it inappropriately may make the output file unusable. Wildcard characters are accepted insectionpatternπ―
If the first character of sectionpattern is an exclamation point (!), then matching sections won't be copied, even if an earlier --only-section on the same command line would otherwise copy them. For example:
--only-section=.text.* --only-section=!.text.foo
This copies all sections matching .text.* but not the section .text.foo π
-R sectionpattern,--remove-section=sectionpatternβ Remove any section matchingsectionpatternfrom the output file. You can give this option more than once. Again, using it inappropriately may make the output file unusable. Wildcard characters are accepted insectionpattern. Using-jand-Rtogether gives undefined behaviour, so maybe don't π ββοΈ
If the first character of sectionpattern is an exclamation point (!), then matching sections won't be removed, even if an earlier --remove-section on the same command line would otherwise remove them. For example:
--remove-section=.text.* --remove-section=!.text.foo
This removes all sections matching the pattern .text.*, but it won't remove the section .text.foo π
--keep-section=sectionpatternβ When removing sections from the output file, keep the sections that matchsectionpatternπ«Ά--remove-relocations=sectionpatternβ Remove non-dynamic relocations from the output file for any section matchingsectionpattern. You can give this option more than once. Be warned: using it inappropriately may make the output file unusable, and trying to remove a dynamic relocation section such as.rela.pltfrom an executable or shared library with--remove-relocations=.pltwon't work. Wildcard characters are accepted insectionpattern. For example:
--remove-relocations=.text.*
This removes the relocations for all sections matching the pattern .text.* π§
If the first character of sectionpattern is an exclamation point (!), then matching sections won't have their relocations removed, even if an earlier --remove-relocations on the same command line would otherwise remove them. For example:
--remove-relocations=.text.* --remove-relocations=!.text.foo
This removes all relocations for sections matching .text.*, but it keeps the relocations for the section .text.foo π
--strip-section-headersβ Strips section headers. This option is specific to ELF files. It implies--strip-alland--merge-notesβ¨-S,--strip-allβ Don't copy relocation and symbol information from the source file. This also deletes debug sections π§Ή-g,--strip-debugβ Don't copy debugging symbols or sections from the source file π--strip-unneededβ Remove every symbol that isn't needed for relocation processing, on top of the debugging symbols and sections that--strip-debugwould strip ποΈ-K symbolname,--keep-symbol=symbolnameβ When stripping symbols, keep the symbolsymbolnameeven if it would normally get stripped. You can give this option more than once π-N symbolname,--strip-symbol=symbolnameβ Don't copy the symbolsymbolnamefrom the source file. You can give this option more than once π«--strip-unneeded-symbol=symbolnameβ Don't copy the symbolsymbolnamefrom the source file unless a relocation needs it. You can give this option more than once π₯Ί-G symbolname,--keep-global-symbol=symbolnameβ okay so this one keeps ONLYsymbolnameglobal πβ¨ Every other symbol gets bumped to local so nobody outside the file can see it. You can use it more than once. β οΈ It can't be combined with--globalize-symbolor--globalize-symbols, so don't mix them up, bestie π--localize-hiddenβ in an ELF object, every symbol with hidden or internal visibility gets marked as local π«£ This one stacks on top of the symbol-specific localization options, like-L.-L symbolname,--localize-symbol=symbolnameβ turns a global or weak symbol calledsymbolnameinto a local one, so it's hidden from the outside world π¦ You can repeat it. Heads up: unique symbols are NOT converted, so they stay as they are π-W symbolname,--weaken-symbol=symbolnameβ makes the symbolsymbolnameweak πΈ Repeatable, obviously.--globalize-symbol=symbolnameβ givessymbolnameglobal scoping, so it's visible outside the file it's defined in π You can use it more than once. β οΈ It can't be used with-Gor--keep-global-symbol, same vibe as before π-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 work ANYWHERE in the name. If the very first character is an exclamation point (!), the switch flips for that symbol. Here's the example:
-w -W !foo -W fo*
This would make objcopy weaken all symbols that start with "fo" EXCEPT for the symbol "foo" π₯Ίβ¨
-x,--discard-allβ doesn't copy any non-global symbols from the source file ποΈ-X,--discard-localsβ doesn't copy the compiler-generated local symbols π€ These usually start withLor...-b byte,--byte=byteβ if you turned on interleaving with--interleave, this starts the range of bytes to keep at thebyteth byte π―bytehas to be somewhere from 0 up to breadth-1, where breadth is whatever you gave to--interleave.-i [breadth],--interleave[=breadth]β only copies a range out of everybreadthbytes π§ Header data is left alone. Pick the starting byte with--byte, and pick how wide the range is with--interleave-width.
This one is super useful for making files to program ROM π§ It's usually paired with an "srec" output target. Also, objcopy will complain if you forget --byte, so don't skip it!
The default interleave breadth is 4. So with --byte set to 0, objcopy would copy the first byte out of every four bytes from the input to the output π
--interleave-width=widthβ used together with--interleave, this copieswidthbytes at a time π The starting point comes from--byte, and the size of the whole range comes from--interleave.
The default for this is 1. Also, width plus the --byte value must not go over the interleave breadth you set with --interleave, or it's not gonna work π
ββοΈ
This is giving two 16-bit flashes sharing a 32-bit bus energy π₯ You make them by passing -b 0 -i 4 --interleave-width=2 and -b 2 -i 4 --interleave-width=2 to two separate objcopy commands. If the input was '12345678', the outputs would be '1256' and '3478' respectively π
-p,--preserve-datesβ sets the access and modification dates of the output file to match the input file π
This one also copies the date stored in a PE format file's header, UNLESS the SOURCE_DATE_EPOCH environment variable is defined. If it is, that variable gets used as the header date instead, read as the number of seconds since the Unix epoch β°
-D,--enable-deterministic-archivesβ operates in deterministic mode π When it copies archive members and writes the archive index, it uses zero for UIDs, GIDs and timestamps, and consistent file modes for all files. Very neat and tidy π
If binutils was configured with --enable-deterministic-archives, this mode is ON by default. You can turn it off with the -U option, below π
-U,--disable-deterministic-archivesβ doesn't operate in deterministic mode π ββοΈ This is the opposite of-D: archive members and the archive index keep their actual UID, GID, timestamp and file mode values.
This is the default UNLESS binutils was configured with --enable-deterministic-archives π«Ά
--debuggingβ converts debugging information, if it's possible π It's not on by default, because only certain debugging formats are supported and the conversion can take forever β³--gap-fill valβ fills the gaps between sections withvalπ§© This applies to the load address (LMA) of the sections. It works by making the lower-address section bigger, and filling that extra space withval.--pad-to addressβ pads the output file up to the load addressaddressπ° It does this by making the last section bigger. The extra space gets filled with whatever--gap-fillsays (zero by default).--set-start valβ sets the start address (a.k.a. the entry address) of the new file tovalπͺ Not every object file format lets you set the start address, so heads up on that one.--change-start incr,--adjust-start incrβ changes the start address (a.k.a. the entry address) by addingincrβ Same catch: not every object file format supports setting the start address.--change-addresses incr,--adjust-vma incrβ changes the VMA and LMA addresses of ALL sections, plus the start address, by addingincrπ Some object file formats don't let section addresses change freely, so keep that in mind.
β οΈ This does NOT relocate the sections! If your program expects sections to load at a certain address, and you use this to move them somewhere else, the program might fail. Yikes π
--change-section-address sectionpattern{=,+,-}val,--adjust-section-vma sectionpattern{=,+,-}valβ sets or changes BOTH the VMA and LMA addresses of any section matchingsectionpatternπ― With=, the section address gets set toval. Otherwise,valgets added to or subtracted from the section address. Check the notes under--change-addressestoo π Ifsectionpatterndoesn't match any sections in the input file, you'll get a warning, UNLESS you use--no-change-warnings.--change-section-lma sectionpattern{=,+,-}valβ sets or changes the LMA address of any sections matchingsectionpatternπ₯ The LMA is where the section gets loaded into memory when the program loads. Usually that's the same as the VMA (the address it lives at while the program runs), but on some systems, especially ones where the program lives in ROM, they can be different π§Έ With=, the section address is set toval. Otherwisevalis added or subtracted. See the comments under--change-addresses. If nothing matchessectionpattern, you get a warning, UNLESS--no-change-warningsis used.--change-section-vma sectionpattern{=,+,-}valβ sets or changes the VMA address of any section matchingsectionpatternπββοΈ The VMA is where the section will be sitting once the program starts running. Normally it's the same as the LMA (where it gets loaded), but again, ROM-based systems can have them differ πͺ With=, the section address is set toval. Otherwisevalgets added or subtracted. See the comments under--change-addresses. If nothing matches, you get a warning, UNLESS--no-change-warningsis used.
Note - changing the VMA of sections in a fully linked binary can be DANGEROUS π There might be code that expects those sections to still live at their old address.
--change-warnings,--adjust-warningsβ if--change-section-address,--change-section-lmaor--change-section-vmais used and the section pattern doesn't match any sections, you get a warning π This is the default behaviour.--no-change-warnings,--no-adjust-warningsβ no warning gets issued if--change-section-addressor--adjust-section-lmaor--adjust-section-vmais used, even when the section pattern doesn't match anything π--set-section-flags sectionpattern=flagsβ sets the flags for any sections matchingsectionpatternπ·οΈ Theflagsargument is a comma separated string of flag names. The recognized names arealloc,contents,load,noload,readonly,code,data,rom,exclude,share,debug, andlarge.
You CAN set the contents flag on a section that doesn't have contents yet. But clearing the contents flag on a section that DOES have contents isn't meaningful, so just remove the section instead ποΈ Not every flag means something for every object file format. For example, the share flag only matters for COFF format files, not ELF ones. The ELF x86-64 specific flag large corresponds to SHF_X86_64_LARGE π§
--set-section-alignment sectionpattern=alignβ sets the alignment for any sections matchingsectionpatternπalignis the alignment in bytes, and it MUST be a power of two, like 1, 2, 4, 8....
Note - setting a section's alignment does NOT automatically align its LMA or VMA addresses. If those need changing too, use --change-section-lma and/or --change-section-vma. Also, changing VMAs can cause problems in fully linked binaries, where there may be code that expects the contents of the sections to still be at their old address π«
β¨ OPTIONS β¨ (continued)
okay bestie, this is where the section stuff gets spicy πΈ
--add-section sectionname=filenameβ π§ Makes a brand new section calledsectionnamewhile the file gets copied. Its contents come fromfilename, and the section ends up exactly the size of that file. This only works on formats that can handle sections with arbitrary names. ngl you might also need--set-section-flagsto give the new section its attributes π--dump-section sectionname=filenameβ π€ The inverse of--add-section! It takes everything insidesectionnameand dumps it intofilename, overwriting anything already in there. It's kinda like--only-section, except it doesn't make a formatted file. It just dumps raw binary data and skips relocations entirely. You can use it more than once π¦--update-section sectionname=filenameβ π Swaps out the existing contents ofsectionnamefor whatever is infilename. The section gets resized to match the file. The section flags stay the same, and for ELF files the section-to-segment mapping stays put too. That's the bit--remove-sectionfollowed by--add-sectioncan't do π You can use this more than once as well.
Heads up: you can update and rename a section in one go! Pass the original name to--update-section, and pass the original and new names to--rename-section. Iconic multitasking π
--add-symbol name=[section:]value[,flags]β β¨ Adds a new symbol callednamewhile copying. You can do this multiple times. If you give a section, the symbol is tied to that section and is relative to it. If you don't, it becomes anABSsymbol. Naming a section that doesn't exist is a fatal error π The value is taken exactly as you typed it, no checking. Not every flag makes sense for every object format. By default the symbol is global. The special flagbefore=othersymslots the new symbol right in front ofothersym. Otherwise, symbols get tacked onto the end of the symbol table in the order you wrote them π--rename-section oldname=newname[,flags]β π·οΈ Renames a section fromoldnametonewname, and you can change its flags toflagswhile you're at it. The perk over using a linker script? Your output stays an object file instead of turning into a linked executable. It takes the same flags as--set-section-flags.
This one is extra helpful with binary input, because binary input always makes a section called .data. Wanna name it .rodata instead, holding binary data? Try this:
objcopy -I binary -O <output_format> -B <architecture> \
--rename-section .data=.rodata,alloc,load,readonly,data,contents \
<input_binary_file> <output_object_file>
--long-section-names {enable,disable,keep}β π Decides what happens to long section names when you're working with "COFF" and "PE-COFF" object formats. The default iskeep, which holds onto long names if the input has them.enableanddisableforce long names on or off in the output. Withdisable, any long names in the input get chopped short.enableonly emits long names if the inputs actually have some, so it's basically the same askeep. The one mystery is whetherenablemight force an empty string table into the output file, and that part is left undefined π€·ββοΈ--change-leading-charβ π€ Some object formats stick a special character at the start of symbol names. The usual suspect is underscore, which compilers love to add before every symbol. This tellsobjcopyto swap the leading character for every symbol when it converts between formats. If both formats use the same leading character, this does nothing. Otherwise it adds, removes, or changes a character as needed π--remove-leading-charβ βοΈ If a global symbol starts with the format's special leading character, this yanks it off. Underscore is the most common one, so this strips the leading underscore from all global symbols. Super handy when you're linking objects from different formats that have different naming vibes. It's different from--change-leading-charbecause it always changes the name when it should, no matter what format the output is π¦--reverse-bytes=numβ π Reverses the bytes in a section that has output contents. For the swap to work, the section length has to be evenly divisible bynum. The reversing happens before any interleaving. This comes in clutch for making ROM images on picky target systems. For example, some boards re-assemble 32-bit words from 8-bit ROMs in little-endian order no matter what the CPU uses, so the ROM's endianness might need changing depending on the programming model π«Ά
Say a section holds these eight bytes: 12345678.
--reverse-bytes=2gives21436587--reverse-bytes=4gives43218765--reverse-bytes=2followed by--reverse-bytes=4on the output file gives34127856
--srec-len=ivalβ π Only matters for srec output. Sets the max length of the Srecords being produced toival. That length includes the address, data, and crc fields π--srec-forceS3β π― Only matters for srec output. StopsS1andS2records from being generated, so you get an S3-only record format π--redefine-sym old=newβ πͺ Renames the symbololdtonew. This is great when you're trying to link two things together that you don't have source for, and their names keep colliding π--redefine-syms=filenameβ π Runs--redefine-symon everyold newsymbol pair listed infilename. The file is a flat list with one pair per line, and hash characters start line comments. You can use this more than once β¨--weakenβ π Makes every global symbol in the file weak. This is useful when you're building an object that'll get linked against other objects using the linker's-Roption. It only does anything with object formats that support weak symbols πΈ--keep-symbols=filenameβ π‘οΈ Runs--keep-symbolon each symbol listed infilename. That file is a flat list with one symbol name per line, and hash characters start line comments. You can use this more than once π--strip-symbols=filenameβ ποΈ Runs--strip-symbolon each symbol listed infilename. Same deal: one symbol name per line, hash comments, and it can be used more than once π«§--strip-unneeded-symbols=filenameβ π§Ή Runs--strip-unneeded-symbolon each symbol listed infilename. One name per line, hash comments, and multiple uses are fine π--keep-global-symbols=filenameβ π Runs--keep-global-symbolon each symbol listed infilename. One name per line, hash comments, can be repeated π¦--localize-symbols=filenameβ π Runs--localize-symbolon each symbol listed infilename. One name per line, hash comments, and you can use it more than once π--globalize-symbols=filenameβ π£ Runs--globalize-symbolon each symbol listed infilename. One name per line, hash comments, repeatable. Note: this one cannot be combined with the-Gor--keep-global-symboloptions π ββοΈ--weaken-symbols=filenameβ π« Runs--weaken-symbolon each symbol listed infilename. One name per line, hash comments, and you can use it more than once π--alt-machine-code=indexβ π’ If the output architecture has alternate machine codes, this uses theindexth code instead of the default. This is useful when a machine gets an official code and the toolchain adopts it, but other apps still rely on the original code. For ELF architectures, if theindexalternative doesn't exist, the value gets treated as an absolute number and stored in thee_machinefield of the ELF header π§--writable-textβ βοΈ Marks the output text as writable. Not every object format cares about this one πΈ--readonly-textβ π Makes the output text write-protected. Also not meaningful for every object format π«Ά--pureβ π Marks the output file as demand paged. Not meaningful for every object format π--impureβ πͺοΈ Marks the output file as impure. Again, only meaningful for some object formats π--prefix-symbols=stringβ π·οΈ Slapsstringin front of every symbol in the output file π--prefix-sections=stringβ π Slapsstringin front of every section name in the output file β¨--prefix-alloc-sections=stringβ π Slaps a prefix onto the front of every allocated section name in the output file, using string as the prefix. β¨--add-gnu-debuglink=path-to-fileβ π¦ Okay so this one creates a.gnu_debuglinksection that points to path-to-file and tucks it into the output file. ngl the file atpath-to-filehas to already exist π. Adding that section also embeds a checksum of the debug info file's contents into it, which is very detail-oriented of it. π
If your debug info file gets built in one spot but won't be installed until later in a different spot, do NOT use the installed path here. π The option will fail because the installed file doesn't exist yet. Instead, keep the debug info file in the current directory and pass it without any directory components, like this:
objcopy --add-gnu-debuglink=foo.debug
At debug time, the debugger goes hunting for the separate debug info file in a bunch of known locations. The exact list depends on the distro you're using, but it usually includes:
- The same directory as the executable.
- A sub-directory of the directory containing the executable, called
.debug. - A global debug directory, such as
/usr/lib/debug.
As long as the debug info file has been installed into one of those spots before the debugger runs, everything should work correctly. πΈ
--keep-section-symbolsβ π§ When you're stripping a file (say with--strip-debugor--strip-unneeded), this keeps any symbols that name sections, even though they'd otherwise get stripped. β¨--keep-file-symbolsβ π§ Same energy as above, but for symbols that name source files. When you're stripping with--strip-debugor--strip-unneeded, these get kept instead of stripped. π--only-keep-debugβ π₯ This strips a file by removing the contents of any sections that--strip-debugwouldn't strip, while leaving the debugging sections intact. For ELF files, all note sections in the output stay put. π
Heads up, bestie: the section headers of the stripped sections are preserved, sizes included, but their contents get tossed. The headers stick around so other tools can match the debuginfo file with the real executable, even if that executable has been moved to a different address space. π«Ά
This option is meant to be paired with --add-gnu-debuglink to create a two-part executable. π One part is the stripped binary, which takes up less RAM and less space in a distribution. The other is a debugging info file, which you only need if you actually want to debug. The suggested steps to make these are:
- Link the executable as normal. Assuming it's called
foo, then... - Run
objcopy --only-keep-debug foo foo.dbgto create a file containing the debugging info. - Run
objcopy --strip-debug footo create a stripped executable. - Run
objcopy --add-gnu-debuglink=foo.dbg footo add a link to the debugging info into the stripped executable.
Note: using .dbg as the extension for the debug info file is totally arbitrary, and the --only-keep-debug step is optional. π You could instead do this:
- Link the executable as normal.
- Copy
footofoo.full. - Run
objcopy --strip-debug foo. - Run
objcopy --add-gnu-debuglink=foo.full foo.
Basically, the file pointed to by --add-gnu-debuglink can be the full executable. It doesn't have to be a file made by --only-keep-debug. π
Note: this switch is only meant for fully linked files. It doesn't make sense on object files, where the debugging info might be incomplete. π Also, the gnu_debuglink feature currently only supports one filename containing debugging info, not multiple filenames on a one-per-object-file basis.
--strip-dwoβ π Removes the contents of all DWARF.dwosections, but leaves the other debugging sections and all symbols intact. This one is built for the compiler to use as part of the-gsplit-dwarfoption, which splits debug info between the.ofile and a separate.dwofile. The compiler generates all the debug info in one file, then uses--extract-dwoto copy the.dwosections into the.dwofile, and then--strip-dwoto remove those sections from the original.ofile. π§--extract-dwoβ π Extracts the contents of all DWARF.dwosections. Check out the--strip-dwooption for more info. π--file-alignment numβ π Sets the file alignment. Sections in the file will always start at file offsets that are multiples of num. It defaults to512. [This option is specific to PE targets.] β¨--heap reserve,--heap reserve,commitβ π§ Reserves the given number of bytes of memory (and optionally commits them) to be used as heap for this program. [This option is specific to PE targets.] π--image-base valueβ π Uses value as the base address of your program or dll. This is the lowest memory location that gets used when your program or dll is loaded. To cut down on relocations and boost dll performance, each dll should have a unique base address and not overlap any other dll. The default is0x400000for executables and0x10000000for dlls. [This option is specific to PE targets.] π¦--section-alignment numβ π [This option is specific to PE targets.] Sets the section alignment field in the PE header, if one is present in the binary. Sections in memory always begin at addresses that are multiples of num. It defaults to0x1000.
Note: if a section's LMA or VMA addresses end up unaligned, and those addresses weren't set with--set-section-lmaor--set-section-vma, and the file has been fully relocated, then a warning message gets issued. From there, it's up to you to decide whether the LMA and VMA need updating. β οΈ
--stack reserve,--stack reserve,commitβ π₯ Reserves the given number of bytes of memory (and optionally commits them) to be used as stack for this program. [This option is specific to PE targets.] π--subsystem which,--subsystem which:major,--subsystem which:major.minorβ π₯οΈ Picks the subsystem your program will run under. The legal values for which arenative,windows,console,posix,efi-app,efi-bsd,efi-rtd,sal-rtd, andxbox. You can also optionally set the subsystem version. Numeric values are accepted for which too. [This option is specific to PE targets.] π--extract-symbolβ π Keeps the file's section flags and symbols, but removes all section data. Specifically, this option:- removes the contents of all sections;
- sets the size of every section to zero; and
- sets the file's start address to zero.
It's used to build a .sym file for a VxWorks kernel. It can also be handy for shrinking a --just-symbols linker input file. πΈ
--compress-debug-sectionsβ ποΈ Compresses DWARF debug sections using zlib with SHF_COMPRESSED from the ELF ABI. Note: if compression would actually make a section larger, it doesn't get compressed. π--compress-debug-sections=none,--compress-debug-sections=zlib,--compress-debug-sections=zlib-gnu,--compress-debug-sections=zlib-gabi,--compress-debug-sections=zstdβ ποΈ For ELF files, these control how DWARF debug sections get compressed.--compress-debug-sections=noneis the same as--decompress-debug-sections.--compress-debug-sections=zliband--compress-debug-sections=zlib-gabiare the same as--compress-debug-sections.--compress-debug-sections=zlib-gnucompresses DWARF debug sections using the obsoleted zlib-gnu format, and the debug sections get renamed to begin with.zdebug.--compress-debug-sections=zstdcompresses DWARF debug sections using zstd. Note: if compression would make a section larger, it's not compressed nor renamed. π--decompress-debug-sectionsβ π«§ Decompresses DWARF debug sections. For a.zdebugsection, the original name gets restored. β¨--elf-stt-common=yes,--elf-stt-common=noβ π§© For ELF files, these decide whether common symbols should be converted to theSTT_COMMONorSTT_OBJECTtype.--elf-stt-common=yesconverts the common symbol type toSTT_COMMON.--elf-stt-common=noconverts it toSTT_OBJECT. π¦--merge-notes,--no-merge-notesβ ποΈ For ELF files, these either attempt or don't attempt to shrink anySHT_NOTEtype sections by removing duplicate notes. π-V,--versionβ π·οΈ Shows the version number of objcopy. π--verilog-data-width=bytesβ π’ For Verilog output, this controls the number of bytes converted for each output data element. The input target controls the endianness of the conversion. π-v,--verboseβ π£ Verbose output: lists all object files modified. For archives,objcopy -Vlists all members of the archive. π₯--helpβ π Shows a summary of the objcopy options. π«Ά--infoβ πΊοΈ Displays a list of all the architectures and object formats available. π@fileβ π Reads command-line options from file. The options read get inserted in place of the original@fileoption. If file doesn't exist or can't be read, the option is treated literally and not removed. π
Options in file are separated by whitespace. To include a whitespace character inside an option, wrap the entire option in either single or double quotes. Any character (including a backslash) can be included by putting a backslash in front of the character you want. The file can contain more @file options too, and those get processed recursively. π§
π¦ SEE ALSO π¦
ld(1), objdump(1), and the Info entries for binutils. π
π COPYRIGHT π
okay so the copyright bit is lowkey important, bestie π«Ά It's 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. π There are no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. π ββοΈ
A copy of the license is included in the section entitled "GNU Free Documentation License". π
bestie, that's the whole page ππ«Ά binutils-2.45 π¦ dated 2025-12-03 πΈ and it's all the OBJCOPY(1) manual, periodt π β¨
π¦ where this page comes from
- ubuntu questing: binutils-common 2.45-7ubuntu1.2
- ubuntu questing: binutils-x86-64-linux-gnu 2.45-7ubuntu1.2
- π girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms