|
From: Dan K. <da...@ke...> - 2009-10-18 13:58:10
|
Thanks to Tom and John, I now use 32 bit opcodes, and it works a lot better :-) My little demo still doesn't quite work when compiled with visual c++ -- valgrind explodes with a SIGSEGV, so either I have a bug, or varargs is different enough to cause trouble. I have to run, but if anyone's curious, here's what I've got so far. - Dan /* Demo of calling VALGRIND_PRINTF * See https://bugs.kde.org/show_bug.cgi?id=210935 * * Works under Linux if compiled natively or if compiled with * mingw32 and run under Wine. * Doesn't quite work yet if compiled under Visual C++. * Dan Kegel 18 Oct 2009 */ #include <malloc.h> #if defined(linux) #include <valgrind/valgrind.h> #elif defined(_WIN32) /* Subset of valgrind.h, ported to win32 for compilers mingw and visual c */ #include <stdlib.h> #include <stdarg.h> enum { VG_USERREQ__PRINTF = 0x1401, } Vg_ClientRequest; #if defined(__GNUC__) /* no changes needed in the gcc case; * valgrind.h just needs conditionals changed a bit * to recongnize that it works under gcc regardless of operating system */ #define __SPECIAL_INSTRUCTION_PREAMBLE \ "roll $3, %%edi ; roll $13, %%edi\n\t" \ "roll $29, %%edi ; roll $19, %%edi\n\t" #define VALGRIND_DO_CLIENT_REQUEST( \ _zzq_rlval, _zzq_default, _zzq_request, \ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ { volatile unsigned int _zzq_args[6]; \ volatile unsigned int _zzq_result; \ _zzq_args[0] = (unsigned int)(_zzq_request); \ _zzq_args[1] = (unsigned int)(_zzq_arg1); \ _zzq_args[2] = (unsigned int)(_zzq_arg2); \ _zzq_args[3] = (unsigned int)(_zzq_arg3); \ _zzq_args[4] = (unsigned int)(_zzq_arg4); \ _zzq_args[5] = (unsigned int)(_zzq_arg5); \ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ /* %EDX = client_request ( %EAX ) */ \ "xchgl %%ebx,%%ebx" \ : "=d" (_zzq_result) \ : "a" (&_zzq_args[0]), "0" (_zzq_default) \ : "cc", "memory" \ ); \ _zzq_rlval = _zzq_result; \ } static int VALGRIND_PRINTF(const char *format, ...) __attribute__((format(__printf__, 1, 2), __unused__)); static int VALGRIND_PRINTF(const char *format, ...) { unsigned long _qzz_res; va_list vargs; va_start(vargs, format); VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF, (unsigned long)format, (unsigned long)vargs, 0, 0, 0); va_end(vargs); return (int)_qzz_res; } #else /* definitions from valgrind.h, ported to visual c */ /* This is for 32 bits; for 64 bits, shift counts are different */ #define __SPECIAL_INSTRUCTION_PREAMBLE __asm { \ __asm rol edi, 0x03 \ __asm rol edi, 0x0d \ __asm rol edi, 0x1d \ __asm rol edi, 0x13 \ } static int VALGRIND_PRINTF(const char *format, ...) { va_list vargs; volatile unsigned int _zzq_args[6]; unsigned int _qzz_res; va_start(vargs, format); _zzq_args[0] = (unsigned int) VG_USERREQ__PRINTF, _zzq_args[1] = (unsigned int) format; _zzq_args[2] = (unsigned int) vargs; _zzq_args[3] = (unsigned int) 0; _zzq_args[4] = (unsigned int) 0; _zzq_args[5] = (unsigned int) 0; __asm mov eax, _zzq_args __asm mov edx, 0 __SPECIAL_INSTRUCTION_PREAMBLE __asm xchg ebx,ebx __asm mov _qzz_res, edx va_end(vargs); return (int)_qzz_res; } #endif /* defined(__GCC__) */ #endif /* defined(_WIN32) */ int main() { char *memory = malloc(10); VALGRIND_PRINTF("Hello, valgrind!\n"); return memory[0]; } |