Skip to content
A tool which allows you to edit source code of any MSVC C++ project live at runtime
Branch: master
Clone or download
Latest commit 9ca9e5c Mar 29, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
source Check ClassID inside the COFF header to distinguish extended COFF fil… Mar 24, 2019
.editorconfig
.gitignore Clean up gitignore Apr 23, 2016
CMakeLists.txt Add simple CMake build script (#24) Mar 21, 2019
LICENSE.md Add license information Dec 8, 2018
README.md Clean up readme Mar 29, 2019
blink.sln
blink.vcxproj
blink.vcxproj.filters Fix linking failing when using "/bigobj" compiler switch Mar 22, 2019

README.md

blink

Build Status

A tool that lets you edit the source code of a Windows C++ application live, while it is running, without having to go through the usual compile-and-restart cycle. It is effectivly a runtime linker that detects changes to source code files, compiles them and links them back into the running application, while patching all updated functions to jump to the new code.

In contrast to similar projects, blink does not require you to modify your C++ project in any way. In fact it works on all x86 and x86-64 applications as long as they were compiled with debug symbols (so that a PDB file is created) and you have their source code somewhere on your system.

Demo

There now is a library which implements the same concept as blink but for Unix based systems: jet-live

Build

There are no dependencies, blink is fully standalone (apart from the Windows SDK). You only need a C++17 compliant version of MSVC 2017. Then just build the provided Visual Studio solution.

A quick overview of what each of the source code files contain:

File Description
blink.cpp Application logic, filesystem watcher, main loop
blink_linker.cpp COFF loader and linker, symbol resolving, function patching
main.cpp Main entry point, remote thread injection, console output loop
coff_reader.cpp Abstraction around COFF to deal with extended OBJ files (/bigobj)
msf_reader.cpp Parser for the MSF file format (which PDB files are based on)
pdb_reader.cpp Parser for the Microsoft PDB file format

Usage

Once you build blink, there are two ways to use it:

  1. Either launch your application via blink:
    blink.exe foo.exe -arguments
  2. Or attach blink to an already running application:
    blink.exe PID where PID is the process ID to attach to

Now simply do changes to any of the source code files of your application and see how they are reflected right away. Keep in mind that since blink patches on a function-level, you need a function that is repeatedly called, since changes are only made visible the next time a function is entered.

If blink has trouble finding the right compilation command-line for your project, make sure to check your build is generating PDB files with the /ZI compile option (blink has to fall back to a default command-line otherwise).

Optionally, if you define the following functions in your application, blink will call them before and after linking, which can be used to synchronize or save/restore application state:

extern "C" void __blink_sync(const char *source_file);
extern "C" void __blink_release(const char *source_file, bool success);

Concept

Here is a quick run-down on how blink works:

When you attach it to an application it will start by finding the path to the matching PDB (program debug database) file generated by the compiler. This information is stored in the executable headers. After finding said file it parses it to obtain the list of source code files that were used to build the application and initialize the symbol table with all internal and external symbols of the application. Then it figures out the common parent path of all user source code files and starts listening for file modifications on that path.

Every time a change is registered, blink looks for the compilation command that was used to compile that source file in the application debug information, executes it to get a new object file reflecting the change and then links that object file into the application process.

The linking for the most part works like a traditional linker would, except that it also replicates some of what the Windows loader would do when you launch an executable, so that it can perform at runtime, rather than at compile-time. It parses the object file (which is in COFF format) and allocates and copies all necessary sections into the application process memory space. It then finds the symbol table of the object file and resolves all of them using symbol information that was previously extracted from the PDB file. The state of global variables is preserved by using the address of the existing symbols, so that the new code references the existing memory, rather than new one. Afterwards the relocation table of the object file is used to adjust all address references in memory to point to the correct addresses. And finally, blink writes a x86 jump instruction to the beginning of all functions in the application that are also part of the new code that was just loaded. This jump targets the new functions, so that every time the old function is called, the call is immediately redirected to the new code.

Contributing

Any contributions to the project are welcomed, it's recommended to use GitHub pull requests.

License

All source code in this repository is licensed under a BSD 2-clause license.

You can’t perform that action at this time.