# hex mode crashes after saving file

I have a a.out file from "hello world" in c:

#include <stdio.h>
#include <stdlib.h>
int main(){
printf("hello world\n");
}


Which I can see in hexdump (file a.out) with command :%!xxd -g1

00000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  .ELF............
00000010: 03 00 3e 00 01 00 00 00 50 10 00 00 00 00 00 00  ..>.....P.......
00000020: 40 00 00 00 00 00 00 00 c3 b8 40 00 00 00 00 00  @.........@.....
00000030: 00 00 00 00 00 40 00 38 00 0b 00 40 00 23 00 22  .....@.8...@.#."
00000040: 00 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00  .........@......
00000050: 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00  .@.......@......
00000060: 00 68 02 00 00 00 00 00 00 68 02 00 00 00 00 00  .h.......h......
00000070: 00 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00  ................
00000080: 00 c2 a8 02 00 00 00 00 00 00 c2 a8 02 00 00 00  ................
00000090: 00 00 00 c2 a8 02 00 00 00 00 00 00 1c 00 00 00  ................
000000a0: 00 00 00 00 1c 00 00 00 00 00 00 00 01 00 00 00  ................
000000b0: 00 00 00 00 01 00 00 00 04 00 00 00 00 00 00 00  ................
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
...


after seeing the hexdump (not modifying), I will try to revert back haxdump to binary with command :%!xxd -r. After which the file cannot be run anymore:

\$./a.out
bash: ./a.out: cannot execute binary file: Exec format error


I have not made any changes. So did vim saved it with some changes, or why cannot bash recognize the format ELF?

• Welcome to Vi and Vim! – filbranden Jun 20 '20 at 14:34
• Does this issue still happen if you open the a.out file using vim -b (for "binary")? Vim will potentially mess up with line endings and possibly add a newline to the very end of the file. It might also mess with encodings. -b should neutralize all that. Check whether it works please? – filbranden Jun 20 '20 at 14:37
• @filbranden is completely correct; binaries will be corrupted when not using vim -b—I know it has to do with encodings/line-endings, and it's not enough to set the options appropriately after the file has loaded. It must be done ahead of time, such as using -b or ++bin options (see :help edit-binary). See also github.com/benknoble/vim-hex/issues/4 – D. Ben Knoble Jun 20 '20 at 15:04

As I started to explain in comments, the issue is described in :help edit-binary:

8. Editing binary files                 *edit-binary*

Although Vim was made to edit text files, it is possible to edit binary
files.  The |-b| Vim argument (b for binary) makes Vim do file I/O in binary
mode, and sets some options for editing binary files ('binary' on, 'textwidth'
to 0, 'modeline' off, 'expandtab' off).  Setting the 'binary' option has the
same effect.  Don't forget to do this before reading the file.

There are a few things to remember when editing binary files:
- When editing executable files the number of characters must not change.
Use only the "R" or "r" command to change text.  Do not delete characters
with "x" or by backspacing.
- Set the 'textwidth' option to 0.  Otherwise lines will unexpectedly be
split in two.
- When there are not many <EOL>s, the lines will become very long.  If you
want to edit a line that does not fit on the screen reset the 'wrap' option.
Horizontal scrolling is used then.  If a line becomes too long (more than
about 32767 characters on the Amiga, much more on 32-bit systems, see
|limits|) you cannot edit that line.  The line will be split when reading
the file.  It is also possible that you get an "out of memory" error when
file.  Otherwise both <CR> <NL> and <NL> are considered to end a line
and when the file is written the <NL> will be replaced with <CR> <NL>.
- <Nul> characters are shown on the screen as ^@.  You can enter them with
"CTRL-V CTRL-@" or "CTRL-V 000"
- To insert a <NL> character in the file split a line.  When writing the
buffer to a file a <NL> will be written for the <EOL>.
- Vim normally appends an <EOL> at the end of the file if there is none.
Setting the 'binary' option prevents this.  If you want to add the final
<EOL>, set the 'endofline' option.  You can also read the value of this
option to see if there was an <EOL> for the last line (you cannot see this
in the text).



Note that the flag must be set before loading the file! This is relevant to my hex-editing plugin as well.

• But how to set that flag -b, when opening file from outside via :%!? As I am doing with the outside program xxd? is it possible? – milanHrabos Jun 20 '20 at 15:44
• You need to either vim -b a.out, or :edit ++bin a.out. Then you should have no troubles with :%!xxd – D. Ben Knoble Jun 20 '20 at 15:53
• @milanHrabos When you use :%! you're filtering the contents of the current buffer, so the buffer options will be preserved. If you opened the buffer with vim -b initially, then that should be preserved over a :%! filter. – filbranden Jun 20 '20 at 15:54
• But thats the thing, is there a filetype or somthing to resolve its actually bin file? because if I forgot to open it with that flag, and will edit it, then it will crash. I would like to "active" bin mode once open as "regular" file. I know manuals says to open it already with the flag, but is it possible to "activate" bin mode once open as regulare file? – milanHrabos Jun 20 '20 at 15:57
• @milanHrabos you can :set binary, but it still won’t work (it’s too late). You might be able to use an autocommand on BufReadPre or something, but it wont work for everything (ie, you could match patterns but not everything is a.out; you could try if the file is executable, but that catches scripts too, etc.). In my opinion, better to remember manually than rely on automation that doesnt work, but I would love to see someone solve that problem. – D. Ben Knoble Jun 20 '20 at 17:31