Convert Windows Object Files Safely with x86_64-w64-mingw32-objcopy
You will use the MinGW cross-toolchain's objcopy to turn a raw file into a Windows x86-64 object, turn that object back into raw bytes, and understand the options used to strip or select sections. The workflow keeps source files intact and gives you a check after each conversion.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a shell, the binutils-mingw-w64-x86-64 package, and a file that you are willing to read. No step needs sudo; use elevated privileges only if your input directory is deliberately restricted.
The commands below use GNU Binutils 2.41.90.20240122 from the installed package. The x86_64-w64-mingw32ucrt-objcopy name is an alias to the same installed manpage and binary behaviour.
1. Confirm the binary and its supported targets
Start with read-only checks. This catches the common mistake of invoking a host objcopy with a different set of BFD targets:
$ command -v x86_64-w64-mingw32-objcopy
/usr/bin/x86_64-w64-mingw32-objcopy
$ x86_64-w64-mingw32-objcopy --version
GNU objcopy (GNU Binutils) 2.41.90.20240122
$ dpkg-query -W -f='${Package} ${Version}\n' binutils-mingw-w64-x86-64
binutils-mingw-w64-x86-64 2.41.90.20240122-1ubuntu1+11.4
List the formats this build knows about before choosing one:
$ x86_64-w64-mingw32-objcopy --info
For this installation, pe-x86-64 is an output target and binary is the raw-data input or output format. Target names are not interchangeable: -I describes the input, -O describes the output, and -B supplies an architecture when the input has none.
Checkpoint
Do not continue until the command resolves to the cross-toolchain binary and the target you need appears in --info.
2. Preserve the original before translating
objcopy INPUT OUTPUT writes a new file. If you omit OUTPUT, it creates a temporary result and destructively renames it over INPUT. That default is convenient for intentional in-place edits and dangerous for experiments.
Use a fresh output name, and check that the input is readable:
$ INPUT=/path/to/payload.bin
$ test -r "$INPUT" && echo readable
readable
$ x86_64-w64-mingw32-objcopy -I binary -O pe-x86-64 -B i386:x86-64 \
"$INPUT" /tmp/payload.o
The command above changes no input. The binary input target treats the file as address-free data. -B i386:x86-64 gives the generated object an x86-64 architecture, while -O pe-x86-64 requests a little-endian Windows COFF object format for this toolchain.
Warn yourself before using any option that removes sections, symbols or relocations. These are file transformations, not reversible metadata toggles. Keep the original or make a separately named copy until the consumer accepts the result.
3. Verify the generated Windows object
Inspect the result with file and the cross-toolchain's objdump if it is installed. The first command is enough to check the format without loading or running the object:
$ file /tmp/payload.o
/tmp/payload.o: Intel amd64 COFF object file, no relocation info, no line number info, not stripped, 1 section, symbol offset=0x4c, 3 symbols, 1st section name ".data"
$ x86_64-w64-mingw32-objdump -t /tmp/payload.o
The exact symbol offset and summary vary with the input length and binutils build. A useful invariant is that the object is recognised as an Intel amd64 COFF object and has a data section. The binary input handler also creates symbols derived from the file name: start, end and size symbols are available to code that links the generated object.
If you need to inspect sections rather than symbols, use the companion tool:
$ x86_64-w64-mingw32-objdump -h /tmp/payload.o
That command is diagnostic only. It does not change the object.
4. Extract the bytes again
To produce a raw memory image, set the output target to binary. Symbols and relocation information are discarded, and the dump begins at the load address of the lowest copied section:
$ x86_64-w64-mingw32-objcopy -O binary \
/tmp/payload.o /tmp/payload-roundtrip.bin
$ file /tmp/payload-roundtrip.bin
/tmp/payload-roundtrip.bin: ASCII text
$ cmp /path/to/payload.bin /tmp/payload-roundtrip.bin
$ wc -c /path/to/payload.bin /tmp/payload-roundtrip.bin
14 /path/to/payload.bin
14 /tmp/payload-roundtrip.bin
28 total
A silent cmp means the files match byte for byte. If the source is an object with gaps or sections at different load addresses, a raw output is a memory image rather than a general-purpose archive of the original file. It will not preserve the original symbols or relocations.
For an S-record instead, use -O srec. Confirm that srec is listed by --info first, and remember that S-record output is still a representation of copied sections, not a way to change the input's endianness.
5. Make a deliberate section or debug transformation
-j SECTION copies only matching sections. -R SECTION removes matching sections. Wildcards are accepted, but using -j and -R together has undefined behaviour in this version of the manual. A wrong pattern can make the output unusable, so inspect the section list first and write to a new file:
$ x86_64-w64-mingw32-objcopy -j .data \
/tmp/payload.o /tmp/payload-data.o
$ file /tmp/payload-data.o
For linked executables, -g or --strip-debug removes debugging symbols and sections. -S or --strip-all is broader: it also removes relocation and symbol information. Treat -S as destructive to debugging and symbol-based workflows. If you need a separate debug file, the documented pattern is to create it with --only-keep-debug, strip the deployable file, then add a .gnu_debuglink with --add-gnu-debuglink.
Do not strip a file merely to make it smaller before checking how it will be debugged, signed or linked. Keep both the original and transformed files until the next tool accepts the result.
6. Diagnose failures without guessing
- File format not recognised: run
--info, then supply the correct-Ionly when automatic detection cannot identify the input. Do not guess a target from the filename. - Wrong architecture: use
-Bonly for architecture-less input such as raw binary data. It is ignored when the input already has a known architecture. - Missing sections or symbols: check the source with
objdump -horobjdump -tbefore adding a pattern or stripping option. - Unexpected output size: remember that raw output follows section load addresses and contains no object metadata.
- Input overwritten: restore it from your backup or version control. If there is no copy, stop;
objcopycannot reconstruct discarded symbols, relocations or debug data.
Done means
- The installed cross-compiler version and BFD targets were checked.
- A raw file was converted to a Windows x86-64 object without changing the source.
- The object was inspected as an Intel amd64 COFF file.
- Raw extraction was verified with
cmpand a byte count. - Section and debug transformations were treated as destructive and written to new paths.
- You know that omitting the output filename enables an in-place replacement.