|
From: Nicholas N. <nj...@cs...> - 2005-03-28 03:26:03
|
On Sun, 27 Mar 2005, Jeremy Fitzhardinge wrote:
>> VG_(init_post_clo_init) ( & ac_post_clo_init );
>> VG_(init_instrument) ( & ac_instrument );
>> VG_(init_handle_client_request)( & ac_handle_client_request );
>>
>> (That's slightly different your suggestion of passing a struct of function
>> pointers, but very similar.)
>
> Yes, I think that's better because it removes the fragility of having a
> structure as part of the interface.
The below patch against the current SVN HEAD (with changelog) is a first
step towards this. Comments are welcome -- Julian, how do you think it
looks doing it with functions rather than naked structs?
N
-----------------------------------------------------------------------------
This change reduces the number of calls to dlsym() when loading tools from a
lot to one. This required two basic changes:
1. Tools are responsible for telling the tool about any functions they
provide that the tool may call. This includes basic functions like
TL_(instrument)(), functions that assist core services such as
TL_(pp_Error)(), and malloc-replacement-related functions like
TL_(malloc)().
2. Tools that replace malloc now specify the size of the heap block redzones
through the VG_DETERMINE_INTERFACE_VERSION macro, rather than with a
variable VG_(vg_malloc_redzone_szB).
One consequence of these changes is that VG_(tool_init_dlsym)() no longer
needs to be generated by gen_toolint.pl.
There are a number of further improvements that could follow on from this one.
- Avoid the confusingly different definitions of the TL_() macro in the
core vs. for tools. Indeed, the functions provided by the tools now don't
need to use the TL_() macro at all, as they can have arbitrary names.
- Remove a lot of the auto-generated stuff in vg_toolint.c and vg_toolint.h
(indeed, it might be possible to not auto-generate these at all, which
would be nice).
- The handling of VgToolInterface is currently split across vg_needs.c and
vg_toolint.c, which isn't nice.
-----------------------------------------------------------------------------
Index: corecheck/cc_main.c
===================================================================
--- corecheck/cc_main.c (revision 3466)
+++ corecheck/cc_main.c (working copy)
@@ -40,13 +40,15 @@
"Copyright (C) 2002-2005, and GNU GPL'd, by Nicholas Nethercote.");
VG_(details_bug_reports_to) (VG_BUGS_TO);
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
VG_(needs_core_errors)();
/* No core events to track */
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
-
void TL_(post_clo_init)(void)
{
}
@@ -61,6 +63,8 @@
{
}
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
+
/*--------------------------------------------------------------------*/
/*--- end cc_main.c ---*/
/*--------------------------------------------------------------------*/
Index: memcheck/mc_main.c
===================================================================
--- memcheck/mc_main.c (revision 3466)
+++ memcheck/mc_main.c (working copy)
@@ -1873,14 +1873,38 @@
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 370 );
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
VG_(needs_core_errors) ();
- VG_(needs_tool_errors) ();
+ VG_(needs_tool_errors) (TL_(eq_Error),
+ TL_(pp_Error),
+ TL_(update_extra),
+ TL_(recognised_suppression),
+ TL_(read_extra_suppression_info),
+ TL_(error_matches_suppression),
+ TL_(get_error_name),
+ TL_(print_extra_suppression_info));
VG_(needs_libc_freeres) ();
- VG_(needs_command_line_options)();
- VG_(needs_client_requests) ();
- VG_(needs_sanity_checks) ();
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+ VG_(needs_client_requests) (TL_(handle_client_request));
+ VG_(needs_sanity_checks) (TL_(cheap_sanity_check),
+ TL_(expensive_sanity_check));
VG_(needs_shadow_memory) ();
+ VG_(malloc_funcs) (TL_(malloc),
+ TL_(__builtin_new),
+ TL_(__builtin_vec_new),
+ TL_(memalign),
+ TL_(calloc),
+ TL_(free),
+ TL_(__builtin_delete),
+ TL_(__builtin_vec_delete),
+ TL_(realloc) );
+
MAC_( new_mem_heap) = & mc_new_mem_heap;
MAC_( ban_mem_heap) = & mc_make_noaccess;
MAC_(copy_mem_heap) = & mc_copy_address_range_state;
@@ -1951,7 +1975,7 @@
}
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 9./8)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 9./8, MALLOC_REDZONE_SZB)
/*--------------------------------------------------------------------*/
/*--- end mc_main.c ---*/
Index: memcheck/mac_malloc_wrappers.c
===================================================================
--- memcheck/mac_malloc_wrappers.c (revision 3466)
+++ memcheck/mac_malloc_wrappers.c (working copy)
@@ -41,9 +41,6 @@
static SizeT cmalloc_n_frees = 0;
static SizeT cmalloc_bs_mallocd = 0;
-/* We want a 16B redzone on heap blocks for Addrcheck and Memcheck */
-SizeT VG_(vg_malloc_redzone_szB) = 16;
-
/* Function pointers for the two tools to track interesting events. */
void (*MAC_(new_mem_heap)) ( Addr a, SizeT len, Bool is_inited ) = NULL;
void (*MAC_(ban_mem_heap)) ( Addr a, SizeT len ) = NULL;
@@ -221,7 +218,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocMalloc,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocMalloc,
MAC_(malloc_list));
}
}
@@ -232,7 +229,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocNew,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocNew,
MAC_(malloc_list));
}
}
@@ -243,7 +240,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocNewVec,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocNewVec,
MAC_(malloc_list));
}
}
@@ -254,7 +251,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, n, align,
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/False, MAC_AllocMalloc,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/False, MAC_AllocMalloc,
MAC_(malloc_list));
}
}
@@ -265,7 +262,7 @@
return NULL;
} else {
return MAC_(new_block) ( tid, 0, nmemb*size1, VG_(clo_alignment),
- VG_(vg_malloc_redzone_szB), /*is_zeroed*/True, MAC_AllocMalloc,
+ MALLOC_REDZONE_SZB, /*is_zeroed*/True, MAC_AllocMalloc,
MAC_(malloc_list));
}
}
@@ -326,19 +323,19 @@
void TL_(free) ( ThreadId tid, void* p )
{
MAC_(handle_free)(
- tid, (Addr)p, VG_(vg_malloc_redzone_szB), MAC_AllocMalloc );
+ tid, (Addr)p, MALLOC_REDZONE_SZB, MAC_AllocMalloc );
}
void TL_(__builtin_delete) ( ThreadId tid, void* p )
{
MAC_(handle_free)(
- tid, (Addr)p, VG_(vg_malloc_redzone_szB), MAC_AllocNew);
+ tid, (Addr)p, MALLOC_REDZONE_SZB, MAC_AllocNew);
}
void TL_(__builtin_vec_delete) ( ThreadId tid, void* p )
{
MAC_(handle_free)(
- tid, (Addr)p, VG_(vg_malloc_redzone_szB), MAC_AllocNewVec);
+ tid, (Addr)p, MALLOC_REDZONE_SZB, MAC_AllocNewVec);
}
void* TL_(realloc) ( ThreadId tid, void* p, SizeT new_size )
@@ -397,19 +394,17 @@
/* First half kept and copied, second half new,
red zones as normal */
- MAC_(ban_mem_heap) ( p_new-VG_(vg_malloc_redzone_szB),
- VG_(vg_malloc_redzone_szB) );
+ MAC_(ban_mem_heap) ( p_new-MALLOC_REDZONE_SZB, MALLOC_REDZONE_SZB );
MAC_(copy_mem_heap)( (Addr)p, p_new, mc->size );
MAC_(new_mem_heap) ( p_new+mc->size, new_size-mc->size, /*inited*/False );
- MAC_(ban_mem_heap) ( p_new+new_size, VG_(vg_malloc_redzone_szB) );
+ MAC_(ban_mem_heap) ( p_new+new_size, MALLOC_REDZONE_SZB );
/* Copy from old to new */
for (i = 0; i < mc->size; i++)
((UChar*)p_new)[i] = ((UChar*)p)[i];
/* Free old memory */
- die_and_free_mem ( tid, mc, prev_chunks_next_ptr,
- VG_(vg_malloc_redzone_szB) );
+ die_and_free_mem ( tid, mc, prev_chunks_next_ptr, MALLOC_REDZONE_SZB );
/* this has to be after die_and_free_mem, otherwise the
former succeeds in shorting out the new block, not the
Index: memcheck/mac_shared.h
===================================================================
--- memcheck/mac_shared.h (revision 3466)
+++ memcheck/mac_shared.h (working copy)
@@ -290,6 +290,8 @@
extern void MAC_(print_common_usage) ( void );
extern void MAC_(print_common_debug_usage) ( void );
+/* We want a 16B redzone on heap blocks for Addrcheck and Memcheck */
+#define MALLOC_REDZONE_SZB 16
/*------------------------------------------------------------*/
/*--- Variables ---*/
Index: massif/ms_main.c
===================================================================
--- massif/ms_main.c (revision 3466)
+++ massif/ms_main.c (working copy)
@@ -1159,8 +1159,6 @@
// Current directory at startup.
static Char* base_dir;
-SizeT VG_(vg_malloc_redzone_szB) = 0;
-
void TL_(pre_clo_init)()
{
VG_(details_name) ("Massif");
@@ -1169,11 +1167,29 @@
VG_(details_copyright_author)("Copyright (C) 2003, Nicholas Nethercote");
VG_(details_bug_reports_to) (VG_BUGS_TO);
+ // Basic functions
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
// Needs
VG_(needs_libc_freeres)();
- VG_(needs_command_line_options)();
- VG_(needs_client_requests) ();
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+ VG_(needs_client_requests) (TL_(handle_client_request));
+ // Malloc replacement
+ VG_(malloc_funcs) (TL_(malloc),
+ TL_(__builtin_new),
+ TL_(__builtin_vec_new),
+ TL_(memalign),
+ TL_(calloc),
+ TL_(free),
+ TL_(__builtin_delete),
+ TL_(__builtin_vec_delete),
+ TL_(realloc) );
+
// Events to track
VG_(init_new_mem_stack_signal) ( new_mem_stack_signal );
VG_(init_die_mem_stack_signal) ( die_mem_stack_signal );
@@ -1812,7 +1828,7 @@
print_summary ( total_ST, heap_ST, heap_admin_ST, stack_ST );
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
/*--- end ms_main.c ---*/
Index: include/tool.h.base
===================================================================
--- include/tool.h.base (revision 3466)
+++ include/tool.h.base (working copy)
@@ -107,16 +107,21 @@
/* Specifies how big the shadow segment should be as a ratio to the
client address space. 0 for no shadow segment. */
float shadow_ratio;
+
+ /* Specifies how big the redzone surrounding each heap block should be.
+ Only relevant for tools that replace malloc() et al. */
+ UInt malloc_redzone_szB;
} ToolInfo;
/* Every tool must include this macro somewhere, exactly once. */
-#define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init, shadow) \
+#define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init, ratio, rz_szB) \
const ToolInfo TL_(tool_info) = { \
.sizeof_ToolInfo = sizeof(ToolInfo), \
.interface_major_version = VG_CORE_INTERFACE_MAJOR_VERSION, \
.interface_minor_version = VG_CORE_INTERFACE_MINOR_VERSION, \
.tl_pre_clo_init = pre_clo_init, \
- .shadow_ratio = shadow, \
+ .shadow_ratio = ratio, \
+ .malloc_redzone_szB = rz_szB, \
};
/*====================================================================*/
@@ -908,15 +913,6 @@
follow the following instructions. You can do it from scratch,
though, if you enjoy that sort of thing. */
-/* Arena size for valgrind's own malloc(); default value is 0, but can
- be overridden by tool -- but must be done so *statically*, eg:
-
- SizeT VG_(vg_malloc_redzone_szB) = 4;
-
- It can't be done from a function like TL_(pre_clo_init)(). So it can't,
- for example, be controlled with a command line option, unfortunately. */
-extern SizeT VG_(vg_malloc_redzone_szB);
-
/* Can be called from TL_(malloc) et al to do the actual alloc/freeing. */
extern void* VG_(cli_malloc) ( SizeT align, SizeT nbytes );
extern void VG_(cli_free) ( void* p );
@@ -947,6 +943,16 @@
/*====================================================================*/
/* ------------------------------------------------------------------ */
+/* Basic tool functions */
+
+extern void VG_(basic_tool_funcs)(
+ void(*post_clo_init)(void),
+ IRBB*(*instrument)(IRBB* bb_in, VexGuestLayout* layout,
+ IRType gWordTy, IRType hWordTy ),
+ void(*fini)(Int)
+);
+
+/* ------------------------------------------------------------------ */
/* Details */
/* Default value for avg_translations_sizeB (in bytes), indicating typical
@@ -995,27 +1001,110 @@
lot like being a member of a type class. */
/* Want to report errors from tool? This implies use of suppressions, too. */
-extern void VG_(needs_tool_errors) ( void );
+extern void VG_(needs_tool_errors) (
+ // Identify if two errors are equal, or equal enough. `res' indicates how
+ // close is "close enough". `res' should be passed on as necessary, eg. if
+ // the Error's `extra' part contains an ExeContext, `res' should be
+ // passed to VG_(eq_ExeContext)() if the ExeContexts are considered. Other
+ // than that, probably don't worry about it unless you have lots of very
+ // similar errors occurring.
+ Bool (*eq_Error)(VgRes res, Error* e1, Error* e2),
+ // Print error context.
+ void (*pp_Error)(Error* err),
+
+ // Should fill in any details that could be postponed until after the
+ // decision whether to ignore the error (ie. details not affecting the
+ // result of TL_(eq_Error)()). This saves time when errors are ignored.
+ // Yuk.
+ // Return value: must be the size of the `extra' part in bytes -- used by
+ // the core to make a copy.
+ UInt (*update_extra)(Error* err),
+
+ // Return value indicates recognition. If recognised, must set skind using
+ // VG_(set_supp_kind)().
+ Bool (*recognised_suppression)(Char* name, Supp* su),
+
+ // Read any extra info for this suppression kind. Most likely for filling
+ // in the `extra' and `string' parts (with VG_(set_supp_{extra, string})())
+ // of a suppression if necessary. Should return False if a syntax error
+ // occurred, True otherwise.
+ Bool (*read_extra_suppression_info)(Int fd, Char* buf, Int nBuf, Supp* su),
+
+ // This should just check the kinds match and maybe some stuff in the
+ // `string' and `extra' field if appropriate (using VG_(get_supp_*)() to
+ // get the relevant suppression parts).
+ Bool (*error_matches_suppression)(Error* err, Supp* su),
+
+ // This should return the suppression name, for --gen-suppressions, or NULL
+ // if that error type cannot be suppressed. This is the inverse of
+ // TL_(recognised_suppression)().
+ Char* (*get_error_name)(Error* err),
+
+ // This should print any extra info for the error, for --gen-suppressions,
+ // including the newline. This is the inverse of
+ // TL_(read_extra_suppression_info)().
+ void (*print_extra_suppression_info)(Error* err)
+);
+
+
/* Is information kept about specific individual basic blocks? (Eg. for
cachegrind there are cost-centres for every instruction, stored at a
basic block level.) If so, it sometimes has to be discarded, because
.so mmap/munmap-ping or self-modifying code (informed by the
DISCARD_TRANSLATIONS user request) can cause one instruction address
to be used for more than one instruction in one program run... */
-extern void VG_(needs_basic_block_discards) ( void );
+extern void VG_(needs_basic_block_discards) (
+ // Should discard any information that pertains to specific basic blocks
+ // or instructions within the address range given.
+ void (*discard_basic_block_info)(Addr a, SizeT size)
+);
/* Tool defines its own command line options? */
-extern void VG_(needs_command_line_options) ( void );
+extern void VG_(needs_command_line_options) (
+ // Return True if option was recognised. Presumably sets some state to
+ // record the option as well.
+ Bool (*process_cmd_line_option)(Char* argv),
+ // Print out command line usage for options for normal tool operation.
+ void (*print_usage)(void),
+
+ // Print out command line usage for options for debugging the tool.
+ void (*print_debug_usage)(void)
+);
+
/* Tool defines its own client requests? */
-extern void VG_(needs_client_requests) ( void );
+extern void VG_(needs_client_requests) (
+ // If using client requests, the number of the first request should be equal
+ // to VG_USERREQ_TOOL_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two
+ // character identification for the string. The second and subsequent
+ // requests should follow.
+ //
+ // This function should use the VG_IS_TOOL_USERREQ macro (in
+ // include/valgrind.h) to first check if it's a request for this tool. Then
+ // should handle it if it's recognised (and return True), or return False if
+ // not recognised. arg_block[0] holds the request number, any further args
+ // from the request are in arg_block[1..]. 'ret' is for the return value...
+ // it should probably be filled, if only with 0.
+ Bool (*handle_client_request)(ThreadId tid, UWord* arg_block, UWord* ret)
+);
/* Tool does stuff before and/or after system calls? */
-extern void VG_(needs_syscall_wrapper) ( void );
+// Nb: If either of the pre_ functions malloc() something to return, the
+// corresponding post_ function had better free() it!
+extern void VG_(needs_syscall_wrapper) (
+ void (* pre_syscall)(ThreadId tid, UInt syscallno),
+ void (*post_syscall)(ThreadId tid, UInt syscallno, Int res)
+);
/* Are tool-state sanity checks performed? */
-extern void VG_(needs_sanity_checks) ( void );
+// Can be useful for ensuring a tool's correctness. TL_(cheap_sanity_check)
+// is called very frequently; TL_(expensive_sanity_check) is called less
+// frequently and can be more involved.
+extern void VG_(needs_sanity_checks) (
+ Bool(*cheap_sanity_check)(void),
+ Bool(*expensive_sanity_check)(void)
+);
/* Do we need to see data symbols? */
extern void VG_(needs_data_syms) ( void );
@@ -1028,6 +1117,22 @@
extern float TL_(shadow_ratio);
/* ------------------------------------------------------------------ */
+/* Malloc replacement */
+
+// The 'v' prefix avoids GCC complaints about overshadowing global names.
+extern void VG_(malloc_funcs)(
+ void* (*vmalloc) ( ThreadId tid, SizeT n ),
+ void* (*v__builtin_new) ( ThreadId tid, SizeT n ),
+ void* (*v__builtin_vec_new) ( ThreadId tid, SizeT n ),
+ void* (*vmemalign) ( ThreadId tid, SizeT align, SizeT n ),
+ void* (*vcalloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ),
+ void (*vfree) ( ThreadId tid, void* p ),
+ void (*v__builtin_delete) ( ThreadId tid, void* p ),
+ void (*v__builtin_vec_delete) ( ThreadId tid, void* p ),
+ void* (*vrealloc) ( ThreadId tid, void* p, SizeT new_size )
+);
+
+/* ------------------------------------------------------------------ */
/* Core events to track */
/* Part of the core from which this call was made. Useful for determining
Index: cachegrind/cg_main.c
===================================================================
--- cachegrind/cg_main.c (revision 3466)
+++ cachegrind/cg_main.c (working copy)
@@ -1132,9 +1132,15 @@
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 155 );
- VG_(needs_basic_block_discards)();
- VG_(needs_command_line_options)();
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+ VG_(needs_basic_block_discards)(TL_(discard_basic_block_info));
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+
/* Get working directory */
tl_assert( VG_(getcwd_alloc)(&base_dir) );
@@ -1162,7 +1168,7 @@
VG_(register_profile_event)(VgpCacheResults, "cache-results");
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
/*--- end cg_main.c ---*/
Index: none/nl_main.c
===================================================================
--- none/nl_main.c (revision 3466)
+++ none/nl_main.c (working copy)
@@ -39,6 +39,10 @@
"Copyright (C) 2002-2005, and GNU GPL'd, by Nicholas Nethercote.");
VG_(details_bug_reports_to) (VG_BUGS_TO);
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
/* No needs, no core events to track */
}
@@ -56,7 +60,7 @@
{
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
/*--- end ---*/
Index: addrcheck/ac_main.c
===================================================================
--- addrcheck/ac_main.c (revision 3466)
+++ addrcheck/ac_main.c (working copy)
@@ -1318,14 +1318,38 @@
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 135 );
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
+
VG_(needs_core_errors) ();
- VG_(needs_tool_errors) ();
+ VG_(needs_tool_errors) (TL_(eq_Error),
+ TL_(pp_Error),
+ TL_(update_extra),
+ TL_(recognised_suppression),
+ TL_(read_extra_suppression_info),
+ TL_(error_matches_suppression),
+ TL_(get_error_name),
+ TL_(print_extra_suppression_info));
VG_(needs_libc_freeres) ();
- VG_(needs_command_line_options)();
- VG_(needs_client_requests) ();
- VG_(needs_sanity_checks) ();
+ VG_(needs_command_line_options)(TL_(process_cmd_line_option),
+ TL_(print_usage),
+ TL_(print_debug_usage));
+ VG_(needs_client_requests) (TL_(handle_client_request));
+ VG_(needs_sanity_checks) (TL_(cheap_sanity_check),
+ TL_(expensive_sanity_check));
VG_(needs_shadow_memory) ();
+ VG_(malloc_funcs) (TL_(malloc),
+ TL_(__builtin_new),
+ TL_(__builtin_vec_new),
+ TL_(memalign),
+ TL_(calloc),
+ TL_(free),
+ TL_(__builtin_delete),
+ TL_(__builtin_vec_delete),
+ TL_(realloc) );
+
MAC_( new_mem_heap) = & ac_new_mem_heap;
MAC_( ban_mem_heap) = & ac_make_noaccess;
MAC_(copy_mem_heap) = & ac_copy_address_range_state;
@@ -1381,7 +1405,7 @@
MAC_(common_fini)( ac_detect_memory_leaks );
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 1./8)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 1./8, MALLOC_REDZONE_SZB)
/*--------------------------------------------------------------------*/
Index: lackey/lk_main.c
===================================================================
--- lackey/lk_main.c (revision 3466)
+++ lackey/lk_main.c (working copy)
@@ -81,6 +81,10 @@
"Copyright (C) 2002-2005, and GNU GPL'd, by Nicholas Nethercote.");
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(details_avg_translation_sizeB) ( 175 );
+
+ VG_(basic_tool_funcs) (TL_(post_clo_init),
+ TL_(instrument),
+ TL_(fini));
}
void TL_(post_clo_init)(void)
@@ -278,7 +282,7 @@
VG_(message)(Vg_UserMsg, "Exit code: %d", exitcode);
}
-VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0)
+VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 0, 0)
/*--------------------------------------------------------------------*/
Index: coregrind/gen_toolint.pl
===================================================================
--- coregrind/gen_toolint.pl (revision 3466)
+++ coregrind/gen_toolint.pl (working copy)
@@ -166,32 +166,6 @@
print "void VG_(init_$func)($ret (*func)($args));\n";
};
$headerguard=$output;
-} elsif ($output eq "initdlsym") {
- $pre = sub () {
- print <<EOF;
-#include <dlfcn.h>
-void VG_(tool_init_dlsym)(void *dlhandle)
-{
- void *ret;
-
-EOF
- };
- $post = sub () {
- print "}\n";
- };
- $generate = sub ($$$@) {
- my ($pfx, $ret, $func, @args) = @_;
- my $args = join ", ", getargtypes(@args);
-
- print <<EOF;
- ret = dlsym(dlhandle, "vgTool_$func");
- if (ret != NULL)
- VG_(init_$func)(($ret (*)($args))ret);
-
-EOF
- };
-
- $passcomment = 0;
}
die "Unknown output format \"$output\"" unless defined $generate;
Index: coregrind/vg_default.c
===================================================================
--- coregrind/vg_default.c (revision 3466)
+++ coregrind/vg_default.c (working copy)
@@ -66,10 +66,6 @@
/*--- Replacing malloc et al ---*/
/*------------------------------------------------------------*/
-/* Default redzone size for CLIENT arena of Valgrind's malloc() */
-__attribute__ ((weak))
-SizeT VG_(vg_malloc_redzone_szB) = 8;
-
Bool VG_(tl_malloc_called_deliberately) = False;
/* If the tool hasn't replaced malloc(), this one can be called
Index: coregrind/vg_main.c
===================================================================
--- coregrind/vg_main.c (revision 3466)
+++ coregrind/vg_main.c (working copy)
@@ -1175,7 +1175,7 @@
/* Find and load a tool, and check it looks ok. Also looks to see if there's
* a matching vgpreload_*.so file, and returns its name in *preloadpath. */
-static void load_tool( const char *toolname, void** handle_out,
+static void load_tool( const char *toolname,
ToolInfo** toolinfo_out, char **preloadpath_out )
{
Bool ok;
@@ -1184,7 +1184,6 @@
void* handle;
ToolInfo* toolinfo;
char* preloadpath = NULL;
- Int* vg_malloc_redzonep;
// XXX: allowing full paths for --tool option -- does it make sense?
// Doesn't allow for vgpreload_<tool>.so.
@@ -1244,13 +1243,9 @@
}
// Set redzone size for V's allocator
- vg_malloc_redzonep = dlsym(handle, VG_STRINGIFY(VG_(vg_malloc_redzone_szB)));
- if ( NULL != vg_malloc_redzonep ) {
- VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
- }
+ VG_(vg_malloc_redzone_szB) = toolinfo->malloc_redzone_szB;
- vg_assert(NULL != handle && NULL != toolinfo);
- *handle_out = handle;
+ vg_assert(NULL != toolinfo);
*toolinfo_out = toolinfo;
*preloadpath_out = preloadpath;
return;
@@ -2422,7 +2417,6 @@
Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
struct exeinfo info;
ToolInfo *toolinfo = NULL;
- void *tool_dlhandle;
Addr client_eip;
Addr sp_at_startup; /* client's SP at the point we gained control. */
UInt * client_auxv;
@@ -2495,7 +2489,7 @@
// p: set-libdir [for VG_(libdir)]
// p: pre_process_cmd_line_options() [for 'tool']
//--------------------------------------------------------------
- load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
+ load_tool(tool, &toolinfo, &preload);
//==============================================================
// Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
@@ -2572,13 +2566,12 @@
//--------------------------------------------------------------
// Init tool: pre_clo_init, process cmd line, post_clo_init
// p: setup_client_stack() [for 'VG_(client_arg[cv]']
- // p: load_tool() [for 'tool']
+ // p: load_tool() [for 'toolinfo']
// p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
// p: parse_procselfmaps [so VG segments are setup so tool can
// call VG_(malloc)]
//--------------------------------------------------------------
(*toolinfo->tl_pre_clo_init)();
- VG_(tool_init_dlsym)(tool_dlhandle);
VG_(sanity_check_needs)();
// If --tool and --help/--help-debug was given, now give the core+tool
Index: coregrind/vg_malloc2.c
===================================================================
--- coregrind/vg_malloc2.c (revision 3466)
+++ coregrind/vg_malloc2.c (working copy)
@@ -329,6 +329,9 @@
// The arena structures themselves.
static Arena vg_arena[VG_N_ARENAS];
+// Redzone size for CLIENT arena of Valgrind's malloc(). Set in vg_main.c.
+SizeT VG_(vg_malloc_redzone_szB);
+
// Functions external to this module identify arenas using ArenaIds,
// not Arena*s. This fn converts the former to the latter.
static Arena* arenaId_to_ArenaP ( ArenaId arena )
Index: coregrind/vg_needs.c
===================================================================
--- coregrind/vg_needs.c (revision 3466)
+++ coregrind/vg_needs.c (working copy)
@@ -36,6 +36,23 @@
Tool data structure initialisation
------------------------------------------------------------------ */
+/*--------------------------------------------------------------------*/
+/* Setting basic functions */
+
+void VG_(basic_tool_funcs)(
+ void(*post_clo_init)(void),
+ IRBB*(*instrument)(IRBB*, VexGuestLayout*, IRType, IRType ),
+ void(*fini)(Int)
+)
+{
+ VG_(tool_interface).tool_post_clo_init = post_clo_init;
+ VG_(tool_interface).tool_instrument = instrument;
+ VG_(tool_interface).tool_fini = fini;
+}
+
+/*--------------------------------------------------------------------*/
+/* Setting details */
+
/* Init with default values. */
VgDetails VG_(details) = {
.name = NULL,
@@ -46,6 +63,23 @@
.avg_translation_sizeB = VG_DEFAULT_TRANS_SIZEB,
};
+/* Use macro because they're so repetitive */
+#define DETAILS(type, detail) \
+ extern void VG_(details_##detail)(type detail) \
+ { \
+ VG_(details).detail = detail; \
+ }
+
+DETAILS(Char*, name)
+DETAILS(Char*, version)
+DETAILS(Char*, description)
+DETAILS(Char*, copyright_author)
+DETAILS(Char*, bug_reports_to)
+DETAILS(UInt, avg_translation_sizeB)
+
+/*--------------------------------------------------------------------*/
+/* Setting needs */
+
VgNeeds VG_(needs) = {
.core_errors = False,
.tool_errors = False,
@@ -115,44 +149,115 @@
#undef CHECK_NOT
}
-/*--------------------------------------------------------------------*/
-/* Setting details */
-
/* Use macro because they're so repetitive */
-#define DETAILS(type, detail) \
- extern void VG_(details_##detail)(type detail) \
- { \
- VG_(details).detail = detail; \
- }
-
-DETAILS(Char*, name)
-DETAILS(Char*, version)
-DETAILS(Char*, description)
-DETAILS(Char*, copyright_author)
-DETAILS(Char*, bug_reports_to)
-DETAILS(UInt, avg_translation_sizeB)
-
-/*--------------------------------------------------------------------*/
-/* Setting needs */
-
-/* Use macro because they're so repetitive */
#define NEEDS(need) \
extern void VG_(needs_##need)(void) \
{ \
VG_(needs).need = True; \
}
+// These ones don't require any tool-supplied functions
NEEDS(libc_freeres)
NEEDS(core_errors)
-NEEDS(tool_errors)
-NEEDS(basic_block_discards)
-NEEDS(command_line_options)
-NEEDS(client_requests)
-NEEDS(syscall_wrapper)
-NEEDS(sanity_checks)
NEEDS(data_syms)
NEEDS(shadow_memory)
+void VG_(needs_basic_block_discards)(
+ void (*discard)(Addr, SizeT)
+)
+{
+ VG_(needs).basic_block_discards = True;
+ VG_(tool_interface).tool_discard_basic_block_info = discard;
+}
+
+void VG_(needs_tool_errors)(
+ Bool (*eq) (VgRes, Error*, Error*),
+ void (*pp) (Error*),
+ UInt (*update) (Error*),
+ Bool (*recog) (Char*, Supp*),
+ Bool (*read_extra) (Int, Char*, Int, Supp*),
+ Bool (*matches) (Error*, Supp*),
+ Char* (*name) (Error*),
+ void (*print_extra)(Error*)
+)
+{
+ VG_(needs).tool_errors = True;
+ VG_(tool_interface).tool_eq_Error = eq;
+ VG_(tool_interface).tool_pp_Error = pp;
+ VG_(tool_interface).tool_update_extra = update;
+ VG_(tool_interface).tool_recognised_suppression = recog;
+ VG_(tool_interface).tool_read_extra_suppression_info = read_extra;
+ VG_(tool_interface).tool_error_matches_suppression = matches;
+ VG_(tool_interface).tool_get_error_name = name;
+ VG_(tool_interface).tool_print_extra_suppression_info = print_extra;
+}
+
+void VG_(needs_command_line_options)(
+ Bool (*process)(Char*),
+ void (*usage)(void),
+ void (*debug_usage)(void)
+)
+{
+ VG_(needs).command_line_options = True;
+ VG_(tool_interface).tool_process_cmd_line_option = process;
+ VG_(tool_interface).tool_print_usage = usage;
+ VG_(tool_interface).tool_print_debug_usage = debug_usage;
+}
+
+void VG_(needs_client_requests)(
+ Bool (*handle)(ThreadId, UWord*, UWord*)
+)
+{
+ VG_(needs).client_requests = True;
+ VG_(tool_interface).tool_handle_client_request = handle;
+}
+
+void VG_(needs_syscall_wrapper)(
+ void(*pre) (ThreadId, UInt),
+ void(*post)(ThreadId, UInt, Int res)
+)
+{
+ VG_(needs).syscall_wrapper = True;
+ VG_(tool_interface).tool_pre_syscall = pre;
+ VG_(tool_interface).tool_post_syscall = post;
+}
+
+void VG_(needs_sanity_checks)(
+ Bool(*cheap)(void),
+ Bool(*expen)(void)
+)
+{
+ VG_(needs).sanity_checks = True;
+ VG_(tool_interface).tool_cheap_sanity_check = cheap;
+ VG_(tool_interface).tool_expensive_sanity_check = expen;
+}
+
+
+/* Replacing malloc() */
+
+extern void VG_(malloc_funcs)(
+ void* (*malloc) ( ThreadId, SizeT ),
+ void* (*__builtin_new) ( ThreadId, SizeT ),
+ void* (*__builtin_vec_new) ( ThreadId, SizeT ),
+ void* (*memalign) ( ThreadId, SizeT, SizeT ),
+ void* (*calloc) ( ThreadId, SizeT, SizeT ),
+ void (*free) ( ThreadId, void* ),
+ void (*__builtin_delete) ( ThreadId, void* ),
+ void (*__builtin_vec_delete) ( ThreadId, void* ),
+ void* (*realloc) ( ThreadId, void*, SizeT )
+)
+{
+ VG_(tool_interface).malloc_malloc = malloc;
+ VG_(tool_interface).malloc___builtin_new = __builtin_new;
+ VG_(tool_interface).malloc___builtin_vec_new = __builtin_vec_new;
+ VG_(tool_interface).malloc_memalign = memalign;
+ VG_(tool_interface).malloc_calloc = calloc;
+ VG_(tool_interface).malloc_free = free;
+ VG_(tool_interface).malloc___builtin_delete = __builtin_delete;
+ VG_(tool_interface).malloc___builtin_vec_delete = __builtin_vec_delete;
+ VG_(tool_interface).malloc_realloc = realloc;
+}
+
/*--------------------------------------------------------------------*/
/*--- end vg_needs.c ---*/
/*--------------------------------------------------------------------*/
Index: coregrind/core.h
===================================================================
--- coregrind/core.h (revision 3466)
+++ coregrind/core.h (working copy)
@@ -337,8 +337,6 @@
extern VgNeeds VG_(needs);
-extern void VG_(tool_init_dlsym)(void *dlhandle);
-
#include "vg_toolint.h"
@@ -386,6 +384,12 @@
// Round-up size for --sloppy-malloc=yes.
#define VG_SLOPPY_MALLOC_SZB 4
+// Arena size for valgrind's own malloc(). Gets set by the 3rd parameter
+// to the VG_DETERMINE_INTERFACE_VERSION macro, because it has to be set before
+// any of the tool's functions get called. So it can't, for example, be
+// controlled with a command line option, unfortunately. */
+extern SizeT VG_(vg_malloc_redzone_szB);
+
extern void* VG_(arena_malloc) ( ArenaId arena, SizeT nbytes );
extern void VG_(arena_free) ( ArenaId arena, void* ptr );
extern void* VG_(arena_calloc) ( ArenaId arena,
Index: coregrind/Makefile.am
===================================================================
--- coregrind/Makefile.am (revision 3466)
+++ coregrind/Makefile.am (working copy)
@@ -124,7 +124,6 @@
$(PERL) $(srcdir)/gen_toolint.pl callwrap < $(srcdir)/toolfuncs.def > $@ || rm -f $@
$(PERL) $(srcdir)/gen_toolint.pl missingfuncs < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
$(PERL) $(srcdir)/gen_toolint.pl initfunc < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
- $(PERL) $(srcdir)/gen_toolint.pl initdlsym < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
$(PERL) $(srcdir)/gen_toolint.pl structdef < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
vg_toolint.h: $(srcdir)/gen_toolint.pl $(srcdir)/toolfuncs.def ./Makefile
|