From: Nicholas Nethercote Date: Thu, 2 Oct 2003 13:44:04 +0000 (+0000) Subject: Moved the MALLOCLIKE and FREELIKE client requests out of memcheck.h, and into X-Git-Tag: svn/VALGRIND_2_1_0~152 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4877ebb17edaaa865c4e0764d16db9daa3fce9a6;p=thirdparty%2Fvalgrind.git Moved the MALLOCLIKE and FREELIKE client requests out of memcheck.h, and into valgrind.h. Although these requests are not implemented by the core, they can be implemented by skins that track heap blocks, eg. Memcheck, Annelid, Massif. This is in preparation for committing Massif to the repository. I think I managed to make the change in a binary-compatible way. The only inconvenience for users is that if they have a client program compiled with the old requests in, Valgrind will abort with an explanatory message that tells them to recompile. Once they've done that (no changes to their program are required), it works again. I even updated the docs. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1881 --- diff --git a/addrcheck/ac_main.c b/addrcheck/ac_main.c index 0190966384..ce653f7467 100644 --- a/addrcheck/ac_main.c +++ b/addrcheck/ac_main.c @@ -1199,7 +1199,9 @@ Bool SK_(handle_client_request) ( ThreadId tid, UInt* arg_block, UInt *ret ) static Int moans = 3; /* Overload memcheck client reqs */ - if (!VG_IS_SKIN_USERREQ('M','C',arg[0])) + if (!VG_IS_SKIN_USERREQ('M','C',arg[0]) + && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0] + && VG_USERREQ__FREELIKE_BLOCK != arg[0]) return False; switch (arg[0]) { diff --git a/coregrind/docs/coregrind_core.html b/coregrind/docs/coregrind_core.html index 41f8c0cf2e..5e9c876e9b 100644 --- a/coregrind/docs/coregrind_core.html +++ b/coregrind/docs/coregrind_core.html @@ -947,6 +947,19 @@ skin-specific documentation for explanations of the skin-specific macros). Memcheck, but for Cachegrind it will always return zero because Cachegrind doesn't report errors.

+

  • VALGRIND_MALLOCLIKE_BLOCK: If your program manages its own + memory instead of using the standard + malloc()/new/new[], skins that track + information about heap blocks will not do nearly as good a + job. For example, Memcheck won't detect nearly as many errors, and the + error messages won't be as informative. To improve this situation, use + this macro just after your custom allocator allocates some new memory. See + the comments in valgrind.h for information on how to use it. +

    +

  • VALGRIND_FREELIKE_BLOCK: This should be used in conjunction + with VALGRIND_MALLOCLIKE_BLOCK. Again, see + memcheck/memcheck.h for information on how to use it. +

  • VALGRIND_NON_SIMD_CALL[0123]: executes a function of 0, 1, 2 or 3 args in the client program on the real CPU, not the virtual CPU that Valgrind normally runs code on. These are used in various ways diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index ef4d49b77f..cc81d96b0b 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -3526,11 +3526,16 @@ void do_client_request ( ThreadId tid ) static Bool whined = False; if (!whined) { + // Allow for requests in core, but defined by skins, which + // have 0 and 0 in their two high bytes. + Char c1 = (arg[0] >> 24) & 0xff; + Char c2 = (arg[0] >> 16) & 0xff; + if (c1 == 0) c1 = '_'; + if (c2 == 0) c2 = '_'; VG_(message)(Vg_UserMsg, "Warning:\n" - " unhandled client request: 0x%x (%c%c+%d). Perhaps\n" - " VG_(needs).client_requests should be set?\n", - arg[0], (arg[0] >> 24) & 0xff, (arg[0] >> 16) & 0xff, - arg[0] & 0xffff); + " unhandled client request: 0x%x (%c%c+0x%x). Perhaps\n" + " VG_(needs).client_requests should be set?\n", + arg[0], c1, c2, arg[0] & 0xffff); whined = True; } } diff --git a/include/valgrind.h b/include/valgrind.h index 17338196c5..a1711fd281 100644 --- a/include/valgrind.h +++ b/include/valgrind.h @@ -132,6 +132,9 @@ /* Some request codes. There are many more of these, but most are not exposed to end-user view. These are the public ones, all of the form 0x1000 + small_number. + + Core ones are in the range 0x00000000--0x0000ffff. The non-public ones + start at 0x2000. */ #define VG_USERREQ_SKIN_BASE(a,b) \ @@ -154,7 +157,11 @@ typedef Valgrind's output to /dev/null and still count errors. */ VG_USERREQ__COUNT_ERRORS = 0x1201, - VG_USERREQ__FINAL_DUMMY_CLIENT_REQUEST + /* These are useful and can be interpreted by any skin that tracks + malloc() et al, by using vg_replace_malloc.c. */ + VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, + VG_USERREQ__FREELIKE_BLOCK = 0x1302, + } Vg_ClientRequest; @@ -231,4 +238,42 @@ typedef _qyy_res; \ }) +/* Mark a block of memory as having been allocated by a malloc()-like + function. `addr' is the start of the usable block (ie. after any + redzone) `rzB' is redzone size if the allocator can apply redzones; + use '0' if not. Adding redzones makes it more likely Valgrind will spot + block overruns. `is_zeroed' indicates if the memory is zeroed, as it is + for calloc(). Put it immediately after the point where a block is + allocated. + + If you're allocating memory via superblocks, and then handing out small + chunks of each superblock, if you don't have redzones on your small + blocks, it's worth marking the superblock with VALGRIND_MAKE_NOACCESS + when it's created, so that block overruns are detected. But if you can + put redzones on, it's probably better to not do this, so that messages + for small overruns are described in terms of the small block rather than + the superblock (but if you have a big overrun that skips over a redzone, + you could miss an error this way). See memcheck/tests/custom_alloc.c + for an example. + + Nb: block must be freed via a free()-like function specified + with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ +#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ + {unsigned int _qzz_res; \ + VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \ + VG_USERREQ__MALLOCLIKE_BLOCK, \ + addr, sizeB, rzB, is_zeroed); \ + } + +/* Mark a block of memory as having been freed by a free()-like function. + `rzB' is redzone size; it must match that given to + VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak + checker. Put it immediately after the point where the block is freed. */ +#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ + {unsigned int _qzz_res; \ + VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \ + VG_USERREQ__FREELIKE_BLOCK, \ + addr, rzB, 0, 0); \ + } + #endif /* __VALGRIND_H */ diff --git a/memcheck/docs/mc_main.html b/memcheck/docs/mc_main.html index 3d469d3da6..aedef6e6ae 100644 --- a/memcheck/docs/mc_main.html +++ b/memcheck/docs/mc_main.html @@ -823,18 +823,6 @@ details of their arguments. be leaked, dubious, reachable and suppressed. Again, useful in test harness code, after calling VALGRIND_DO_LEAK_CHECK.

    -

  • VALGRIND_MALLOCLIKE_BLOCK: If your program manages its own - memory instead of using the standard - malloc()/new/new[], Memcheck will - not detect nearly as many errors, and the error messages won't be as - informative. To improve this situation, use this macro just after your - custom allocator allocates some new memory. See the comments in - memcheck/memcheck.h for information on how to use it. -

    -

  • VALGRIND_FREELIKE_BLOCK: This should be used in conjunction - with VALGRIND_MALLOCLIKE_BLOCK. Again, see - memcheck/memcheck.h for information on how to use it. -

  • VALGRIND_GET_VBITS and VALGRIND_SET_VBITS: allow you to get and set the V (validity) bits for an address range. You should probably only set V bits that you diff --git a/memcheck/mac_needs.c b/memcheck/mac_needs.c index e0dbbf4e90..ef5fff4821 100644 --- a/memcheck/mac_needs.c +++ b/memcheck/mac_needs.c @@ -827,7 +827,12 @@ void MAC_(common_fini)(void (*leak_check)(void)) Bool MAC_(handle_common_client_requests)(ThreadId tid, UInt* arg, UInt* ret ) { - UInt* argv = (UInt*)arg; + Char* err = + "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n" + " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n" + " program to incorporate the updates in the Valgrind header files.\n" + " You shouldn't need to change the text of your program at all.\n" + " Everything should then work as before. Sorry for the bother.\n"; // Not using 'tid' here because MAC_(new_block)() and MAC_(handle_free)() // grab it themselves. But what they grab should match 'tid', check @@ -846,22 +851,27 @@ Bool MAC_(handle_common_client_requests)(ThreadId tid, UInt* arg, UInt* ret ) *ret = 0; return True; } + case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE: + case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE: + VG_(skin_panic)(err); + case VG_USERREQ__MALLOCLIKE_BLOCK: { - Addr p = (Addr)argv[1]; - UInt sizeB = argv[2]; - UInt rzB = argv[3]; - Bool is_zeroed = (Bool)argv[4]; + Addr p = (Addr)arg[1]; + UInt sizeB = arg[2]; + UInt rzB = arg[3]; + Bool is_zeroed = (Bool)arg[4]; MAC_(new_block) ( p, sizeB, rzB, is_zeroed, MAC_AllocCustom ); return True; } case VG_USERREQ__FREELIKE_BLOCK: { - Addr p = (Addr)argv[1]; - UInt rzB = argv[2]; + Addr p = (Addr)arg[1]; + UInt rzB = arg[2]; MAC_(handle_free) ( p, rzB, MAC_AllocCustom ); return True; } + default: return False; } diff --git a/memcheck/mc_clientreqs.c b/memcheck/mc_clientreqs.c index 53a2b982b0..56d177306c 100644 --- a/memcheck/mc_clientreqs.c +++ b/memcheck/mc_clientreqs.c @@ -150,7 +150,9 @@ Bool SK_(handle_client_request) ( ThreadId tid, UInt* arg, UInt* ret ) Bool ok; Addr bad_addr; - if (!VG_IS_SKIN_USERREQ('M','C',arg[0])) + if (!VG_IS_SKIN_USERREQ('M','C',arg[0]) + && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0] + && VG_USERREQ__FREELIKE_BLOCK != arg[0]) return False; switch (arg[0]) { diff --git a/memcheck/memcheck.h b/memcheck/memcheck.h index b3204f6ad0..5db9900a54 100644 --- a/memcheck/memcheck.h +++ b/memcheck/memcheck.h @@ -80,8 +80,14 @@ typedef VG_USERREQ__CHECK_READABLE, VG_USERREQ__DO_LEAK_CHECK, VG_USERREQ__COUNT_LEAKS, - VG_USERREQ__MALLOCLIKE_BLOCK, - VG_USERREQ__FREELIKE_BLOCK, + + /* These two have been moved into core, because they are useful for + any skin that tracks heap blocks. Hence the suffix. But they're + still here for backwards compatibility, although Valgrind will + abort with an explanatory message if you use them. */ + VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE, + VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE, + VG_USERREQ__GET_VBITS, VG_USERREQ__SET_VBITS } Vg_MemCheckClientRequest; @@ -190,47 +196,23 @@ typedef &leaked, &dubious, &reachable, &suppressed);\ } -#endif - -/* Mark a block of memory as having been allocated by a malloc()-like - function. `addr' is the start of the usable block (ie. after any - redzone) `rzB' is redzone size if the allocator can apply redzones; - use '0' if not. Adding redzones makes it more likely Valgrind will spot - block overruns. `is_zeroed' indicates if the memory is zeroed, as it is - for calloc(). Put it immediately after the point where a block is - allocated. - - If you're allocating memory via superblocks, and then handing out small - chunks of each superblock, if you don't have redzones on your small - blocks, it's worth marking the superblock with VALGRIND_MAKE_NOACCESS - when it's created, so that block overruns are detected. But if you can - put redzones on, it's probably better to not do this, so that messages - for small overruns are described in terms of the small block rather than - the superblock (but if you have a big overrun that skips over a redzone, - you could miss an error this way). See memcheck/tests/custom_alloc.c - for an example. - - Nb: block must be freed via a free()-like function specified - with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ -#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ +/* These two have been moved to valgrind.h; still here so that a warning can + be printed out for any programs using the old ones. */ +#define VALGRIND_MALLOCLIKE_BLOCK__OLD_DO_NOT_USE(addr, sizeB, rzB, is_zeroed)\ {unsigned int _qzz_res; \ VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \ VG_USERREQ__MALLOCLIKE_BLOCK, \ addr, sizeB, rzB, is_zeroed); \ } - -/* Mark a block of memory as having been freed by a free()-like function. - `rzB' is redzone size; it must match that given to - VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak - checker. Put it immediately after the point where the block is freed. */ -#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ +#define VALGRIND_FREELIKE_BLOCK__OLD_DO_NOT_USE(addr, rzB) \ {unsigned int _qzz_res; \ VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \ VG_USERREQ__FREELIKE_BLOCK, \ addr, rzB, 0, 0); \ } + /* Get in zzvbits the validity data for the zznbytes starting at zzsrc. Return values: 0 if not running on valgrind @@ -270,3 +252,6 @@ typedef czzdst, czzvbits, zznbytes,0 ); \ _qzz_res; \ })) + +#endif +