Apr16Written by:SuperUser
Friday, April 16, 2010 
A few customers have asked for a simpler way to use Jinx that does not require the use of jinx_assert. Typically they have a large code base and replacing all asserts with jinx_assert, and modifying each source file to include jinx.h is a burden. There is a way to tap into the existing assert located in MSVCRT. The code for this (compatible with Visual Studio 2008) can be download here.
If we look at assert.h from the standard MSVC header files, we see the following line:
#define assert(_Expression) (void)( (!!(_Expression)) || \
(_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )
This is a fairly typical looking assert macro, which simply evaluates the expression (the !!(_Expression)) and then relies on the C evaluation rules to only invoke _wassert if the result is false. Invoking _wassert also uses the fairly typical approach of grabbing the current file and line info from the preprocessor, and stringifying the expression, handing everything off to a library function for display.
One method of tapping all asserts without explicitly changing them to jinx_assert is to modify the standard include assert.h to look like this:
#include "jinx.h"
#define assert(_Expression) (void)( (!!(_Expression)) || \
(_jinx_assert_failure(), \
_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )
This follows the MSVC assert macro model, but inserts an invocation into _jinx_assert_failure prior to a call to _wassert. (As an aside, we’ll leave it as an exercise for the reader to parse the peculiar yet legitimate use of the comma).
Suppose you don’t want to modify assert.h
Suppose you work in an environment where modifying assert.h isn’t acceptable, or placing an assert.h in your local source tree to override it isn’t accepted, or, more likely, you are linking against binary libraries that contain asserts, but you cannot recompile them. How do you use Jinx in those cases? All hope is not lost!
There are two methods by which the ordinary MSVCRT assert can be tapped into and which one you choose to use will depend on whether you are linking against MSVCRT statically or dynamically. In both cases, the essence of the tap is the same. You’ll note above that when an assert fires the function that does the heavy lifting is _wassert. We could simply provide our own version of _wassert and ensure that it is called in the appropriate places. This is more work than it seems as a decode of _wassert suggests there’s significant functionality there to replicate. Fortunately, however, there’s a simpler approach. A quick disassembly of the stock _wassert code looks like this:
_wassert:
000000014000111C: 48 89 5C 24 20 mov qword ptr [rsp+20h],rbx
0000000140001121: 55 push rbp
0000000140001122: 56 push rsi
0000000140001123: 57 push rdi
0000000140001124: 41 54 push r12
0000000140001126: 41 55 push r13
0000000140001128: 41 56 push r14
000000014000112A: 41 57 push r15
000000014000112C: 48 81 EC A0 06 00 00 sub rsp,6A0h
0000000140001133: 48 8B 05 36 A3 02 00 mov rax,qword ptr [__security_cookie]
000000014000113A: 48 33 C4 xor rax,rsp
000000014000113D: 48 89 84 24 90 06 00 00 mov qword ptr [rsp+690h],rax
0000000140001145: 4C 8B E9 mov r13,rcx
0000000140001148: B9 03 00 00 00 mov ecx,3
000000014000114D: 45 8B F0 mov r14d,r8d
0000000140001150: 48 8B F2 mov rsi,rdx
0000000140001153: E8 60 2D 00 00 call _set_error_mode
...
Note the call to _set_error_mode with(3). The trick to (easily) tapping into assert is to simply provide our own version of _set_error_mode, which is a far simpler function roughly providing this functionality:
int _set_error_mode(int x) {
int old_error_mode;
old_error_mode = __error_mode;
if (x != _REPORT_ERROR_MODE)
__error_mode = x;
return old_error_mode;
}A simple tap would be:
#include "jinx.h"
int _set_error_mode(int x) {
int old_error_mode;
_jinx_assert_failure();
old_error_mode = __error_mode;
if (x != _REPORT_ERROR_MODE)
__error_mode = x;
return old_error_mode;
}
This is close to what we want, but has the unfortunate consequence of invoking _jinx_assert_failure any time _set_error_mode is invoked. In most cases this should be fine: _jinx_assert_failure() doesn’t actually stop your program, it simply tells Jinx to “magnet in” on that section of code for execution, and how many times do we ever really call _set_error_mode anyway? It is possible to do a little better, however, by only invoking _jinx_assert_failure() if _wassert is in the call stack. This is accomplished through a simple filter:
// Are we being called from assert?
int _set_error_mode(int x) {
int old_error_mode;
void **rsp;
int i;
rsp = (void **)&old_error_mode;
for (i = 0; i < 64; i++) {
if (rsp[i] >= (void *)_wassert &&
(unsigned char *) rsp[i] < ((unsigned char *)_wassert + 512))
_jinx_assert_failure();
}
...
So, by simply writing a C file and placing a _set_error_mode call in it we can hook into the underlying _wassert of any statically linked MSVC program. This works because symbols are “weak” (in GCC parlance). Our custom _set_error_mode can override the one contained in the MSVCRT static library.
Life is more complex if MSVCRT is in a DLL.
If you link against MSVCRT as a DLL then life gets a tad more complex. Linking occurs at runtime, and a local version of _set_error_mode cannot override the explicit DLL import that occurs on that symbol elsewhere. Fortunately, there’s a tried and true Windows way to solve this problem, you hook the DLL call. The general practice of hooking is covered extensively on the net, so we’ll just describe the simple version we employ (and we’ll stick to the 64 bit implementation, although the code above contains both the 32 and 64 bit versions). Here, we need a little assistance at runtime to hook _set_error_mode, so the following function must be invoked (we suggest immediately after jinx_register_application):
void _jinx_install_assert_handler() {
unsigned char *ptr8;
unsigned long long *ptr64;
void *ptrv;
DWORD old_protections;
ptrv = (void *)_set_error_mode;
ptr8 = (unsigned char *)ptrv;
VirtualProtect(ptrv, 64, PAGE_EXECUTE_READWRITE, &old_protections);
ptr8[0] = 0x48; // mov rax, 64bit_constant
ptr8[1] = 0xb8;
ptr64 = (unsigned long long *) &ptr8[2];
*ptr64 = (unsigned long long) __jinx_set_error_mode;
ptr8[10] = 0xff; // jmp rax
ptr8[11] = 0xe0;
}
The first few lines of this function acquire the (at runtime linked DLL) address of _set_error_mode. The next line modifies the OS level protections on this code such that we can write to it (don’t worry, this is within process, Windows will proudly make you a per-process copy of that bit of code, so hooking the DLL in one process doesn’t hook the DLL system wide). Finally the next few lines insert a far jump to our own implementation of set_error_mode. It looks ugly, but its functional.
Tapping into structure exceptions for good measure
Since we’ve come this far we might as well let Jinx know about any structured and C++ exceptions that occur in your code. Fortunately this is far simpler to do:
static LONG CALLBACK _jinx_seh_handler(PEXCEPTION_POINTERS ei) {
_jinx_assert_failure();
return EXCEPTION_CONTINUE_SEARCH;
}
void jinx_install_structured_exception_handlers() {
AddVectoredExceptionHandler(1, _jinx_seh_handler);
}In all of these cases, its important to recognize that _jinx_assert_failure is just a magnet. It makes Jinx “home in” on that execution path. So just as it tries to make assert’s fire, it will now also try and make exceptions occur.