I highly recommend the Handmade Hero series referred to in this blog post. I've been following the archives on YouTube (at 2x speed). Casey Muratori is an engaging presenter and I'm rediscovering my love of low-level programming.
I know the Visual Studio C++ debugger has edit-and-continue functionality. It would be nice to read how that is implemented, since it's obviously much more invasive than this.
I don't know how Visual Studio does it, but Apple did implement a feature called "fix and continue" for gdb (it was very dependend on XCode, so it could not be merged to mainline). The implementation was described like this:
"It was pointed out that I never said what F&C _is_. It's a feature for debugging your program, where you can modify your sources mid-debug-session, and the debugger will "patch" in the new code. At a very high level, the source file you're modifying is built as a shared library, gdb executes inferior function calls to load that shared library into the program, gdb finds all old versions of all
functions contained in that shared library and writes trampolines in the prologues to jump to the new versions of those functions, and gdb redirects all file-static (including global) variables in that shared library to point to the statics/globals in the original executable."
This way of script like interactive programming in C with dynamic libraries is quite known in game programming. The game code in Quake 2, Quake 3, Doom 3, Half Life and even the rendering module in Quake 2 [0] was written that way. In addition to the obvious advantage of interactive programming, dynamic libraries also served as a great way to abstract over submodules like the render and sound engine and made it possible to have a in runtime switchable opengl- and software-renderer.
Haven't anyone made a framework along these lines? The main thing I would like this framework to handle for me is cross-platform capability: shared library implementation is different on each operating system, unfortunately for this method.
I have been watching the Handmade Hero stream (and following along by typing the same code locally), but I am behind about 2 weeks. So I was really surprised and delighted to see that this article turned about to be about him and his project.
The way that he is doing cross-platform code for the game is interesting. The platform layer contains main() (or WinMain() in Windows) and is rewritten for each platform. It isn't written as an abstract layer that the game calls. Instead, it sets up a buffer for one frame of video and a circular buffer for sound. Then it calls a function in the game code which is responsible for updating that. The platform code passes a pointer to the video buffer, sound buffer, playing Input (joystick/keyboard), etc. So the game code is completely portable; it is called by the platform code which is native for the actual platform. For example, the Win32 code creates the Window, handles Windows events, initializes DirectSound, and polls XInput for controller state. (It is also why this technique is possible, as they mention, the game layer does not use any external libraries and doesn't allocate its own memory using malloc.)
So, to answer your question: the way to do this, if you're doing the way they do, would be completely different between platforms (Win32 vs unix at the very least), but you don't need to implement it in a generic/abstract way that hides the operating system. They wouldn't write a framework for this. Instead, you would write it into the platform specific code in the (relatively small) platform layer.
Incidentally, the Varnish HTTP cache uses this technique; whenever the config is reloaded, the config files are translated to C, compiled to a shared library, and loaded into the running server process.