I try to write a C code such that executing its binary a.out changes the a.out file itself.
For example, I want to write foo.c like:
% gcc foo.c
% a.out
Hello world!
% a.out
Bus error
%
I try to write a C code such that executing its binary a.out changes the a.out file itself.
For example, I want to write foo.c like:
% gcc foo.c
% a.out
Hello world!
% a.out
Bus error
%
This is not possible to do in a portable way (the way the executable is structured will be different on every system - ELF vs .exe, amb64 vs ARM), but you can bundle something like libgcc or libclang with your output file which should allow codegeneration + compilation.
Look at the code for the clang executable here which should give you some good ideas.
What you might do (in pseudo code):
string myNewCode("#include <stdio.h>\nint main(int argc, char *argv[]){ printf(\"Bus error\\n\");return 1; }");
var compiler = new Compiler();
var temp_file = new tempFile();
compiler->compile(myNewCode, temp_file);
move_file(temp_file, argv[0]);
(secondary edit: having giving this a little more thought, this is completely possible and portable with libclang)
Not portably, no.
In many flavors of Windows, you can't modify the executable of a program being run. This is often highly annoying, even when doing something "more sane" than what you're proposing.
In Linux I think it would be fine, just open argv[0] and modify it. Of course if your process was loaded off the path you migth have issues locating the proper file, but there should be some /sys entry or something that can lead you (down) to the absolute path.
argv[0] is the program itself? Wow! I only thought it was the name of the program.open(argv[0], ...) to open the file that contains the running program for modification./proc/$pid/exe is a symlink to the program file./proc/$pid/mem and modify it? I'm just asking, never done it myself. I know that you can open /dev/mem and modify it, with crashtastic sequences, so I guess it's usage might be the same.I went ahead an tried it. The example below works on Linux as per your spec (Beware, this is hacky, non-dynamic code!)
#include <stdio.h>
const char str1[]="Hello world!"; //12 chars + \0
// echo -n "Bus error"| wc -c # 9 + \0 -- need to pad by 3
int main(int argc, char const * const argv[]){
puts(str1);
system("sed 's/Hello world!/Bus error\\x0\\x0\\x0/' a.out -i~\n"
"rm a.out~\n");
return 0;
}
You can't write to that file in place though (unless you want to bring the app down to a noisy crash). Using -i~ doesn't write in place, but rather moves the original file to a.out~, while creating a modified copy named a.out. (The OS continues reading the same file regardless of the name change. Removing/unlinking is also OK -- Linux programs can continue accessing unlinked files if they had opened them (without closing) before the unlinking).