From: Nicholas Nethercote Date: Tue, 10 May 2005 04:37:01 +0000 (+0000) Subject: Modularised the core/tool interface ('details', 'needs' and VG_(tdict)) X-Git-Tag: svn/VALGRIND_3_0_0~666 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=247e241160bc004e50f069575fc2f2c2155e11b0;p=thirdparty%2Fvalgrind.git Modularised the core/tool interface ('details', 'needs' and VG_(tdict)) into a new module m_tooliface. Pretty straightforward. Touches a lot of files because many files use this interface and so need to include the headers for the new module. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3652 --- diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index 02fccc1bb8..b82d452d05 100644 --- a/cachegrind/cg_main.c +++ b/cachegrind/cg_main.c @@ -31,6 +31,7 @@ #include "tool.h" #include "pub_tool_mallocfree.h" +#include "pub_tool_tooliface.h" #include "cg_arch.h" #include "cg_sim.c" diff --git a/corecheck/cc_main.c b/corecheck/cc_main.c index 213e4a208d..bae14a82dc 100644 --- a/corecheck/cc_main.c +++ b/corecheck/cc_main.c @@ -30,6 +30,7 @@ */ #include "tool.h" +#include "pub_tool_tooliface.h" static void cc_post_clo_init(void) { diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 4a9ddc9937..0d01f4bf7a 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -46,6 +46,7 @@ noinst_HEADERS = \ pub_core_sigframe.h \ pub_core_stacktrace.h \ pub_core_syscalls.h \ + pub_core_tooliface.h \ ume.h \ vg_symtab2.h \ vg_symtypes.h @@ -65,11 +66,12 @@ valgrind_LDFLAGS=-static -g valgrind_LDADD= stage2_SOURCES = \ + m_debuglog.c \ m_errormgr.c \ m_execontext.c \ m_mallocfree.c \ m_stacktrace.c \ - m_debuglog.c \ + m_tooliface.c \ ume.c \ \ vg_scheduler.c \ @@ -78,7 +80,6 @@ stage2_SOURCES = \ vg_main.c \ vg_messages.c \ vg_mylibc.c \ - vg_needs.c \ vg_dummy_profile.c \ vg_signals.c \ vg_symtab2.c \ diff --git a/coregrind/amd64/state.c b/coregrind/amd64/state.c index 1ab749f3a1..ebee8f2651 100644 --- a/coregrind/amd64/state.c +++ b/coregrind/amd64/state.c @@ -7,8 +7,8 @@ This file is part of Valgrind, a dynamic binary instrumentation framework. - Copyright (C) 2000-2005 Nicholas Nethercote - njn@valgrind.org + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -29,6 +29,7 @@ */ #include "core.h" +#include "pub_core_tooliface.h" #include "amd64_private.h" #include @@ -236,4 +237,3 @@ Int VGA_(ptrace_setregs_from_tst)(Int pid, ThreadArchState* arch) /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ - diff --git a/coregrind/core.h b/coregrind/core.h index 8c2aece47f..0ab6bc53fe 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -298,165 +298,6 @@ extern void VG_(done_profiling) ( void ); #define VGP_POPCC(x) if (VG_(clo_profile)) VG_(popcc)(x) -/* --------------------------------------------------------------------- - Tool-related types - ------------------------------------------------------------------ */ -/* These structs are not exposed to tools to mitigate possibility of - binary-incompatibilities when the core/tool interface changes. Instead, - set functions are provided (see include/tool.h). */ -typedef - struct { - Char* name; - Char* version; - Char* description; - Char* copyright_author; - Char* bug_reports_to; - UInt avg_translation_sizeB; - } - VgDetails; - -extern VgDetails VG_(details); - -typedef - struct { - Bool libc_freeres; - Bool core_errors; - Bool tool_errors; - Bool basic_block_discards; - Bool no_longer_used_1; // for backwards compatibility - Bool command_line_options; - Bool client_requests; - Bool no_longer_used_0; // for backwards compatibility - Bool syscall_wrapper; - Bool sanity_checks; - Bool data_syms; - Bool shadow_memory; - } - VgNeeds; - -extern VgNeeds VG_(needs); - -typedef struct { - // --------------------------------------------- - // 'Needs' and related functions - // --------------------------------------------- - // Basic functions - void (*tool_pre_clo_init) (void); - void (*tool_post_clo_init)(void); - IRBB* (*tool_instrument) (IRBB*, VexGuestLayout*, IRType, IRType); - void (*tool_fini) (Int); - - // VG_(needs).core_errors - // (none) - - // VG_(needs).tool_errors - Bool (*tool_eq_Error) (VgRes, Error*, Error*); - void (*tool_pp_Error) (Error*); - UInt (*tool_update_extra) (Error*); - Bool (*tool_recognised_suppression) (Char*, Supp*); - Bool (*tool_read_extra_suppression_info) (Int, Char*, Int, Supp*); - Bool (*tool_error_matches_suppression) (Error*, Supp*); - Char* (*tool_get_error_name) (Error*); - void (*tool_print_extra_suppression_info)(Error*); - - // VG_(needs).basic_block_discards - void (*tool_discard_basic_block_info)(Addr, SizeT); - - // VG_(needs).command_line_options - Bool (*tool_process_cmd_line_option)(Char*); - void (*tool_print_usage) (void); - void (*tool_print_debug_usage) (void); - - // VG_(needs).client_requests - Bool (*tool_handle_client_request)(ThreadId, UWord*, UWord*); - - // VG_(needs).syscall_wrapper - void (*tool_pre_syscall) (ThreadId, UInt); - void (*tool_post_syscall)(ThreadId, UInt, Int); - - // VG_(needs).sanity_checks - Bool (*tool_cheap_sanity_check)(void); - Bool (*tool_expensive_sanity_check)(void); - - // --------------------------------------------- - // Event tracking functions - // --------------------------------------------- - void (*track_new_mem_startup) (Addr, SizeT, Bool, Bool, Bool); - void (*track_new_mem_stack_signal)(Addr, SizeT); - void (*track_new_mem_brk) (Addr, SizeT); - void (*track_new_mem_mmap) (Addr, SizeT, Bool, Bool, Bool); - - void (*track_copy_mem_remap) (Addr, Addr, SizeT); - void (*track_change_mem_mprotect) (Addr, SizeT, Bool, Bool, Bool); - void (*track_die_mem_stack_signal)(Addr, SizeT); - void (*track_die_mem_brk) (Addr, SizeT); - void (*track_die_mem_munmap) (Addr, SizeT); - - VGA_REGPARM(1) void (*track_new_mem_stack_4) (Addr); - VGA_REGPARM(1) void (*track_new_mem_stack_8) (Addr); - VGA_REGPARM(1) void (*track_new_mem_stack_12)(Addr); - VGA_REGPARM(1) void (*track_new_mem_stack_16)(Addr); - VGA_REGPARM(1) void (*track_new_mem_stack_32)(Addr); - void (*track_new_mem_stack)(Addr, SizeT); - - VGA_REGPARM(1) void (*track_die_mem_stack_4) (Addr); - VGA_REGPARM(1) void (*track_die_mem_stack_8) (Addr); - VGA_REGPARM(1) void (*track_die_mem_stack_12)(Addr); - VGA_REGPARM(1) void (*track_die_mem_stack_16)(Addr); - VGA_REGPARM(1) void (*track_die_mem_stack_32)(Addr); - void (*track_die_mem_stack)(Addr, SizeT); - - void (*track_ban_mem_stack)(Addr, SizeT); - - void (*track_pre_mem_read) (CorePart, ThreadId, Char*, Addr, SizeT); - void (*track_pre_mem_read_asciiz)(CorePart, ThreadId, Char*, Addr); - void (*track_pre_mem_write) (CorePart, ThreadId, Char*, Addr, SizeT); - void (*track_post_mem_write) (CorePart, ThreadId, Addr, SizeT); - - void (*track_pre_reg_read) (CorePart, ThreadId, Char*, OffT, SizeT); - void (*track_post_reg_write)(CorePart, ThreadId, OffT, SizeT); - void (*track_post_reg_write_clientcall_return)(ThreadId, OffT, SizeT, Addr); - - void (*track_thread_run)(ThreadId); - - void (*track_post_thread_create)(ThreadId, ThreadId); - void (*track_post_thread_join) (ThreadId, ThreadId); - - void (*track_pre_mutex_lock) (ThreadId, void*); - void (*track_post_mutex_lock) (ThreadId, void*); - void (*track_post_mutex_unlock)(ThreadId, void*); - - void (*track_pre_deliver_signal) (ThreadId, Int sigNo, Bool); - void (*track_post_deliver_signal)(ThreadId, Int sigNo); - - void (*track_init_shadow_page)(Addr); - - // --------------------------------------------- - // malloc/free replacements - // --------------------------------------------- - void* (*malloc_malloc) (ThreadId, SizeT); - void* (*malloc___builtin_new) (ThreadId, SizeT); - void* (*malloc___builtin_vec_new) (ThreadId, SizeT); - void* (*malloc_memalign) (ThreadId, SizeT, SizeT); - void* (*malloc_calloc) (ThreadId, SizeT, SizeT); - void (*malloc_free) (ThreadId, void*); - void (*malloc___builtin_delete) (ThreadId, void*); - void (*malloc___builtin_vec_delete)(ThreadId, void*); - void* (*malloc_realloc) (ThreadId, void*, SizeT); - -} VgToolInterface; - -extern VgToolInterface VG_(tdict); - - - -/* --------------------------------------------------------------------- - Exports of vg_needs.c - ------------------------------------------------------------------ */ - -void VG_(sanity_check_needs)(void); - - /* --------------------------------------------------------------------- Exports of vg_intercept.c ------------------------------------------------------------------ */ @@ -1110,25 +951,6 @@ extern const Int VG_(tramp_syscall_offset); extern const Int VG_(tramp_gettimeofday_offset); extern const Int VG_(tramp_time_offset); -/* --------------------------------------------------------------------- - Things relating to the used tool - ------------------------------------------------------------------ */ - -// Note the use of C's comma operator here -- it means that we execute both -// statements, and the rvalue of the whole thing is the rvalue of the last -// statement. This lets us say "x = VG_TDICT_CALL(...)" in the required -// places, while still checking the assertion. -#define VG_TDICT_CALL(fn, args...) \ - ( tl_assert2(VG_(tdict).fn, \ - "you forgot to set VgToolInterface function '" #fn "'"), \ - VG_(tdict).fn(args) ) - -#define VG_TRACK(fn, args...) \ - do { \ - if (VG_(tdict).track_##fn) \ - VG_(tdict).track_##fn(args); \ - } while(0) - // --------------------------------------------------------------------- // Architecture-specific things defined in eg. x86/*.c // --------------------------------------------------------------------- diff --git a/coregrind/linux/core_os.c b/coregrind/linux/core_os.c index 7b25cb113c..c5d990d5e5 100644 --- a/coregrind/linux/core_os.c +++ b/coregrind/linux/core_os.c @@ -1,4 +1,35 @@ + +/*--------------------------------------------------------------------*/ +/*--- OS-specific stuff. linux/core_os.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + #include "core.h" +#include "pub_core_tooliface.h" void VGA_(os_state_clear)(ThreadState *tst) { @@ -169,3 +200,7 @@ Bool VGA_(client_request)(ThreadId tid, UWord *args) return handled; } + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/linux/sema.c b/coregrind/linux/sema.c index e15392d17b..09b6efce30 100644 --- a/coregrind/linux/sema.c +++ b/coregrind/linux/sema.c @@ -1,3 +1,34 @@ + +/*--------------------------------------------------------------------*/ +/*--- Semaphore stuff. linux/sema.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + (except where noted below) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + #include "core.h" #if FUTEX_SEMA @@ -6,8 +37,7 @@ Taken from futex-2.2/usersem.c Based on work by Matthew Kirkwood . - */ - +*/ #define FUTEX_PASSED (-(1024 * 1024 * 1024)) @@ -110,3 +140,9 @@ void VGO_(sema_up)(vg_sema_t *sema) } #endif /* FUTEX_SEMA */ + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ + + diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c index b4e1a876c3..eb70990d69 100644 --- a/coregrind/m_aspacemgr/aspacemgr.c +++ b/coregrind/m_aspacemgr/aspacemgr.c @@ -33,6 +33,7 @@ #include "core.h" #include "pub_core_aspacemgr.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" /* Define to debug the memory-leak-detector. */ diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c index 70ccb093b2..264e03f1c6 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -32,6 +32,7 @@ #include "pub_core_errormgr.h" #include "pub_core_execontext.h" #include "pub_core_stacktrace.h" +#include "pub_core_tooliface.h" /*------------------------------------------------------------*/ /*--- Globals ---*/ diff --git a/coregrind/m_sigframe/sigframe-amd64-linux.c b/coregrind/m_sigframe/sigframe-amd64-linux.c index 8c765c4993..df1e085434 100644 --- a/coregrind/m_sigframe/sigframe-amd64-linux.c +++ b/coregrind/m_sigframe/sigframe-amd64-linux.c @@ -30,8 +30,9 @@ */ #include "core.h" -#include "pub_core_sigframe.h" #include "pub_core_aspacemgr.h" +#include "pub_core_sigframe.h" +#include "pub_core_tooliface.h" #include "libvex_guest_amd64.h" diff --git a/coregrind/m_sigframe/sigframe-x86-linux.c b/coregrind/m_sigframe/sigframe-x86-linux.c index e19cac72f3..9df64f9298 100644 --- a/coregrind/m_sigframe/sigframe-x86-linux.c +++ b/coregrind/m_sigframe/sigframe-x86-linux.c @@ -30,9 +30,9 @@ */ #include "core.h" -#include "pub_core_sigframe.h" #include "pub_core_aspacemgr.h" /* find_segment */ - +#include "pub_core_sigframe.h" +#include "pub_core_tooliface.h" #include "libvex_guest_x86.h" diff --git a/coregrind/m_syscalls/syscalls-amd64-linux.c b/coregrind/m_syscalls/syscalls-amd64-linux.c index 2d253c9302..fb4e754cc1 100644 --- a/coregrind/m_syscalls/syscalls-amd64-linux.c +++ b/coregrind/m_syscalls/syscalls-amd64-linux.c @@ -33,6 +33,7 @@ #include "pub_core_aspacemgr.h" #include "pub_core_sigframe.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" #include "priv_syscalls.h" diff --git a/coregrind/m_syscalls/syscalls-linux.c b/coregrind/m_syscalls/syscalls-linux.c index 028701f6dc..1902b2440c 100644 --- a/coregrind/m_syscalls/syscalls-linux.c +++ b/coregrind/m_syscalls/syscalls-linux.c @@ -30,6 +30,7 @@ #include "core.h" #include "pub_core_aspacemgr.h" +#include "pub_core_tooliface.h" #include "priv_syscalls.h" /* --------------------------------------------------------------------- diff --git a/coregrind/m_syscalls/syscalls-x86-linux.c b/coregrind/m_syscalls/syscalls-x86-linux.c index 201da46bfb..f3eeeaa6bc 100644 --- a/coregrind/m_syscalls/syscalls-x86-linux.c +++ b/coregrind/m_syscalls/syscalls-x86-linux.c @@ -38,6 +38,7 @@ #include "pub_core_aspacemgr.h" #include "pub_core_sigframe.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" #include "priv_syscalls.h" diff --git a/coregrind/m_syscalls/syscalls.c b/coregrind/m_syscalls/syscalls.c index 66d4e1dc50..82bf2e568f 100644 --- a/coregrind/m_syscalls/syscalls.c +++ b/coregrind/m_syscalls/syscalls.c @@ -32,6 +32,7 @@ #include "pub_core_aspacemgr.h" #include "pub_core_stacktrace.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" #include "priv_syscalls.h" diff --git a/coregrind/vg_needs.c b/coregrind/m_tooliface.c similarity index 99% rename from coregrind/vg_needs.c rename to coregrind/m_tooliface.c index 9627a61b71..f007eaa958 100644 --- a/coregrind/vg_needs.c +++ b/coregrind/m_tooliface.c @@ -30,6 +30,7 @@ */ #include "core.h" +#include "pub_core_tooliface.h" // The core/tool dictionary of functions (initially zeroed, as we want it) VgToolInterface VG_(tdict); diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h index 0debc0dde8..1c01eceb59 100644 --- a/coregrind/pub_core_aspacemgr.h +++ b/coregrind/pub_core_aspacemgr.h @@ -1,7 +1,6 @@ /*--------------------------------------------------------------------*/ -/*--- The address space manager. ---*/ -/*--- pub_core_aspacemgr.h ---*/ +/*--- The address space manager. pub_core_aspacemgr.h ---*/ /*--------------------------------------------------------------------*/ /* diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h new file mode 100644 index 0000000000..e695c73dc7 --- /dev/null +++ b/coregrind/pub_core_tooliface.h @@ -0,0 +1,220 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core/tool interface. pub_core_tooliface.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PUB_CORE_TOOLIFACE_H +#define __PUB_CORE_TOOLIFACE_H + +#include "pub_tool_tooliface.h" + +//-------------------------------------------------------------------- +// PURPOSE: This module encapsulates the key parts of the core/tool +// interface: 'details', 'needs' and 'trackable events'. +//-------------------------------------------------------------------- + +// Note the use of C's comma operator here -- it means that we execute both +// statements, and the rvalue of the whole thing is the rvalue of the last +// statement. This lets us say "x = VG_TDICT_CALL(...)" in the required +// places, while still checking the assertion. +#define VG_TDICT_CALL(fn, args...) \ + ( tl_assert2(VG_(tdict).fn, \ + "you forgot to set VgToolInterface function '" #fn "'"), \ + VG_(tdict).fn(args) ) + +#define VG_TRACK(fn, args...) \ + do { \ + if (VG_(tdict).track_##fn) \ + VG_(tdict).track_##fn(args); \ + } while(0) + +/* These structs are not exposed to tools to mitigate possibility of + binary-incompatibilities when the core/tool interface changes. Instead, + set functions are provided (see include/tool.h). */ + +/* --------------------------------------------------------------------- + 'Details' + ------------------------------------------------------------------ */ + +typedef + struct { + Char* name; + Char* version; + Char* description; + Char* copyright_author; + Char* bug_reports_to; + UInt avg_translation_sizeB; + } + VgDetails; + +extern VgDetails VG_(details); + +/* --------------------------------------------------------------------- + 'Needs' + ------------------------------------------------------------------ */ + +typedef + struct { + Bool libc_freeres; + Bool core_errors; + Bool tool_errors; + Bool basic_block_discards; + Bool no_longer_used_1; // for backwards compatibility + Bool command_line_options; + Bool client_requests; + Bool no_longer_used_0; // for backwards compatibility + Bool syscall_wrapper; + Bool sanity_checks; + Bool data_syms; + Bool shadow_memory; + } + VgNeeds; + +extern VgNeeds VG_(needs); + +/* --------------------------------------------------------------------- + The dictionary of callable tool functions + ------------------------------------------------------------------ */ + +typedef struct { + // -- 'Needs'-related functions ---------------------------------- + // Basic functions + void (*tool_pre_clo_init) (void); + void (*tool_post_clo_init)(void); + IRBB* (*tool_instrument) (IRBB*, VexGuestLayout*, IRType, IRType); + void (*tool_fini) (Int); + + // VG_(needs).core_errors + // (none) + + // VG_(needs).tool_errors + Bool (*tool_eq_Error) (VgRes, Error*, Error*); + void (*tool_pp_Error) (Error*); + UInt (*tool_update_extra) (Error*); + Bool (*tool_recognised_suppression) (Char*, Supp*); + Bool (*tool_read_extra_suppression_info) (Int, Char*, Int, Supp*); + Bool (*tool_error_matches_suppression) (Error*, Supp*); + Char* (*tool_get_error_name) (Error*); + void (*tool_print_extra_suppression_info)(Error*); + + // VG_(needs).basic_block_discards + void (*tool_discard_basic_block_info)(Addr, SizeT); + + // VG_(needs).command_line_options + Bool (*tool_process_cmd_line_option)(Char*); + void (*tool_print_usage) (void); + void (*tool_print_debug_usage) (void); + + // VG_(needs).client_requests + Bool (*tool_handle_client_request)(ThreadId, UWord*, UWord*); + + // VG_(needs).syscall_wrapper + void (*tool_pre_syscall) (ThreadId, UInt); + void (*tool_post_syscall)(ThreadId, UInt, Int); + + // VG_(needs).sanity_checks + Bool (*tool_cheap_sanity_check)(void); + Bool (*tool_expensive_sanity_check)(void); + + // -- Event tracking functions ------------------------------------ + void (*track_new_mem_startup) (Addr, SizeT, Bool, Bool, Bool); + void (*track_new_mem_stack_signal)(Addr, SizeT); + void (*track_new_mem_brk) (Addr, SizeT); + void (*track_new_mem_mmap) (Addr, SizeT, Bool, Bool, Bool); + + void (*track_copy_mem_remap) (Addr, Addr, SizeT); + void (*track_change_mem_mprotect) (Addr, SizeT, Bool, Bool, Bool); + void (*track_die_mem_stack_signal)(Addr, SizeT); + void (*track_die_mem_brk) (Addr, SizeT); + void (*track_die_mem_munmap) (Addr, SizeT); + + VGA_REGPARM(1) void (*track_new_mem_stack_4) (Addr); + VGA_REGPARM(1) void (*track_new_mem_stack_8) (Addr); + VGA_REGPARM(1) void (*track_new_mem_stack_12)(Addr); + VGA_REGPARM(1) void (*track_new_mem_stack_16)(Addr); + VGA_REGPARM(1) void (*track_new_mem_stack_32)(Addr); + void (*track_new_mem_stack)(Addr, SizeT); + + VGA_REGPARM(1) void (*track_die_mem_stack_4) (Addr); + VGA_REGPARM(1) void (*track_die_mem_stack_8) (Addr); + VGA_REGPARM(1) void (*track_die_mem_stack_12)(Addr); + VGA_REGPARM(1) void (*track_die_mem_stack_16)(Addr); + VGA_REGPARM(1) void (*track_die_mem_stack_32)(Addr); + void (*track_die_mem_stack)(Addr, SizeT); + + void (*track_ban_mem_stack)(Addr, SizeT); + + void (*track_pre_mem_read) (CorePart, ThreadId, Char*, Addr, SizeT); + void (*track_pre_mem_read_asciiz)(CorePart, ThreadId, Char*, Addr); + void (*track_pre_mem_write) (CorePart, ThreadId, Char*, Addr, SizeT); + void (*track_post_mem_write) (CorePart, ThreadId, Addr, SizeT); + + void (*track_pre_reg_read) (CorePart, ThreadId, Char*, OffT, SizeT); + void (*track_post_reg_write)(CorePart, ThreadId, OffT, SizeT); + void (*track_post_reg_write_clientcall_return)(ThreadId, OffT, SizeT, Addr); + + void (*track_thread_run)(ThreadId); + + void (*track_post_thread_create)(ThreadId, ThreadId); + void (*track_post_thread_join) (ThreadId, ThreadId); + + void (*track_pre_mutex_lock) (ThreadId, void*); + void (*track_post_mutex_lock) (ThreadId, void*); + void (*track_post_mutex_unlock)(ThreadId, void*); + + void (*track_pre_deliver_signal) (ThreadId, Int sigNo, Bool); + void (*track_post_deliver_signal)(ThreadId, Int sigNo); + + void (*track_init_shadow_page)(Addr); + + // -- malloc/free replacements ----------------------------------- + void* (*malloc_malloc) (ThreadId, SizeT); + void* (*malloc___builtin_new) (ThreadId, SizeT); + void* (*malloc___builtin_vec_new) (ThreadId, SizeT); + void* (*malloc_memalign) (ThreadId, SizeT, SizeT); + void* (*malloc_calloc) (ThreadId, SizeT, SizeT); + void (*malloc_free) (ThreadId, void*); + void (*malloc___builtin_delete) (ThreadId, void*); + void (*malloc___builtin_vec_delete)(ThreadId, void*); + void* (*malloc_realloc) (ThreadId, void*, SizeT); + +} VgToolInterface; + +extern VgToolInterface VG_(tdict); + +/* --------------------------------------------------------------------- + Miscellaneous functions + ------------------------------------------------------------------ */ + +void VG_(sanity_check_needs)(void); + +#endif // __PUB_CORE_TOOLIFACE_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index ba89b423d9..71196fe10c 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -37,6 +37,7 @@ #include "pub_core_errormgr.h" #include "pub_core_execontext.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" #include #include diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index caf5af2d36..750d59ba05 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -35,6 +35,7 @@ #include "pub_core_debuglog.h" /* VG_(debugLog_vprintf) */ #include "pub_core_stacktrace.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" /* --------------------------------------------------------------------- diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 4a4eacc4b0..d0ee0d80d6 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -64,6 +64,7 @@ #include "pub_core_replacemalloc.h" #include "pub_core_stacktrace.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" /* --------------------------------------------------------------------- Types and globals for the scheduler. diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c index 4496b2025b..79d2d97454 100644 --- a/coregrind/vg_signals.c +++ b/coregrind/vg_signals.c @@ -85,6 +85,7 @@ #include "pub_core_errormgr.h" #include "pub_core_sigframe.h" #include "pub_core_syscalls.h" +#include "pub_core_tooliface.h" /* Define to give more sanity checking for signals. */ diff --git a/coregrind/vg_symtab2.c b/coregrind/vg_symtab2.c index 23d5a51fa2..1f1b861221 100644 --- a/coregrind/vg_symtab2.c +++ b/coregrind/vg_symtab2.c @@ -34,8 +34,9 @@ #include "vg_symtab2.h" #include "pub_core_aspacemgr.h" +#include "pub_core_tooliface.h" -#include /* ELF defns */ +#include /* ELF defns */ static SegInfo* segInfo = NULL; diff --git a/coregrind/vg_symtypes.c b/coregrind/vg_symtypes.c index 10c421b5f2..6b5f4dbe4c 100644 --- a/coregrind/vg_symtypes.c +++ b/coregrind/vg_symtypes.c @@ -30,6 +30,7 @@ #include "core.h" #include "vg_symtypes.h" #include "pub_core_debuglog.h" /* VG_(debugLog_vprintf) */ +#include "pub_core_tooliface.h" typedef enum { TyUnknown, /* unknown type */ diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c index b28d0e93a5..a4218bfbab 100644 --- a/coregrind/vg_translate.c +++ b/coregrind/vg_translate.c @@ -31,6 +31,7 @@ #include "core.h" #include "pub_core_aspacemgr.h" +#include "pub_core_tooliface.h" /*------------------------------------------------------------*/ diff --git a/coregrind/vg_transtab.c b/coregrind/vg_transtab.c index 69f725427f..535184d0d4 100644 --- a/coregrind/vg_transtab.c +++ b/coregrind/vg_transtab.c @@ -30,6 +30,7 @@ */ #include "core.h" +#include "pub_core_tooliface.h" /* #define DEBUG_TRANSTAB */ @@ -575,11 +576,8 @@ void VG_(init_tt_tc) ( void ) "(startup of code management)"); /* Figure out how big each tc area should be. */ - avg_codeszQ - = (VG_(details).avg_translation_sizeB + 7) / 8; - - tc_sector_szQ - = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ); + avg_codeszQ = (VG_(details).avg_translation_sizeB + 7) / 8; + tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ); /* Ensure the calculated value is not way crazy. */ vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE); diff --git a/coregrind/x86-linux/ldt.c b/coregrind/x86-linux/ldt.c index e35ac14c88..968de80766 100644 --- a/coregrind/x86-linux/ldt.c +++ b/coregrind/x86-linux/ldt.c @@ -84,6 +84,7 @@ */ #include "core.h" +#include "pub_core_tooliface.h" #include "x86_private.h" #include "libvex_guest_x86.h" diff --git a/coregrind/x86/state.c b/coregrind/x86/state.c index f74e71130d..161c6c261e 100644 --- a/coregrind/x86/state.c +++ b/coregrind/x86/state.c @@ -29,6 +29,7 @@ */ #include "core.h" +#include "pub_core_tooliface.h" #include "x86_private.h" #include @@ -345,4 +346,3 @@ Int VGA_(ptrace_setregs_from_tst)(Int pid, ThreadArchState* arch) /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ - diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index 0677c8098b..4a028b8788 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -32,6 +32,7 @@ #include "tool.h" #include "pub_tool_mallocfree.h" #include "pub_tool_replacemalloc.h" +#include "pub_tool_tooliface.h" #include "helgrind.h" diff --git a/include/Makefile.am b/include/Makefile.am index 75fdaeac56..c346bbfeef 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -17,6 +17,7 @@ incinc_HEADERS = \ pub_tool_mallocfree.h \ pub_tool_replacemalloc.h\ pub_tool_stacktrace.h \ + pub_tool_tooliface.h \ valgrind.h BUILT_SOURCES = valgrind.h diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h new file mode 100644 index 0000000000..f5840b5704 --- /dev/null +++ b/include/pub_tool_tooliface.h @@ -0,0 +1,408 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core/tool interface. pub_tool_tooliface.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PUB_TOOL_TOOLIFACE_H +#define __PUB_TOOL_TOOLIFACE_H + +/* ------------------------------------------------------------------ */ +/* The interface version */ + +/* The version number indicates binary-incompatible changes to the + interface; if the core and tool versions don't match, Valgrind + will abort. */ +#define VG_CORE_INTERFACE_VERSION 8 + +typedef struct _ToolInfo { + Int sizeof_ToolInfo; + Int interface_version; + + /* Initialise tool. Must do the following: + - initialise the `details' struct, via the VG_(details_*)() functions + - register any helpers called by generated code + + May do the following: + - initialise the `needs' struct to indicate certain requirements, via + the VG_(needs_*)() functions + - initialize all the tool's entrypoints via the VG_(init_*)() functions + - register any tool-specific profiling events + - any other tool-specific initialisation + */ + void (*tl_pre_clo_init) ( void ); + + /* Specifies how big the shadow segment should be as a ratio to the + client address space. 0 for no shadow segment. */ + float shadow_ratio; +} ToolInfo; + +/* Every tool must include this macro somewhere, exactly once. */ +#define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init, shadow) \ + const ToolInfo VG_(tool_info) = { \ + .sizeof_ToolInfo = sizeof(ToolInfo), \ + .interface_version = VG_CORE_INTERFACE_VERSION, \ + .tl_pre_clo_init = pre_clo_init, \ + .shadow_ratio = shadow, \ + }; + +/* ------------------------------------------------------------------ */ +/* Basic tool functions */ + +extern void VG_(basic_tool_funcs)( + // Do any initialisation that can only be done after command line + // processing. + void (*post_clo_init)(void), + + // Instrument a basic block. Must be a true function, ie. the same input + // always results in the same output, because basic blocks can be + // retranslated. Unless you're doing something really strange... + IRBB* (*instrument)(IRBB* bb_in, VexGuestLayout* layout, + IRType gWordTy, IRType hWordTy ), + + // Finish up, print out any results, etc. `exitcode' is program's exit + // code. The shadow can be found with VG_(get_exit_status_shadow)(). + void (*fini)(Int) +); + +/* ------------------------------------------------------------------ */ +/* Details */ + +/* Default value for avg_translations_sizeB (in bytes), indicating typical + code expansion of about 6:1. */ +#define VG_DEFAULT_TRANS_SIZEB 100 + +/* Information used in the startup message. `name' also determines the + string used for identifying suppressions in a suppression file as + belonging to this tool. `version' can be NULL, in which case (not + surprisingly) no version info is printed; this mechanism is designed for + tools distributed with Valgrind that share a version number with + Valgrind. Other tools not distributed as part of Valgrind should + probably have their own version number. */ +extern void VG_(details_name) ( Char* name ); +extern void VG_(details_version) ( Char* version ); +extern void VG_(details_description) ( Char* description ); +extern void VG_(details_copyright_author) ( Char* copyright_author ); + +/* Average size of a translation, in bytes, so that the translation + storage machinery can allocate memory appropriately. Not critical, + setting is optional. */ +extern void VG_(details_avg_translation_sizeB) ( UInt size ); + +/* String printed if an `tl_assert' assertion fails or VG_(tool_panic) + is called. Should probably be an email address. */ +extern void VG_(details_bug_reports_to) ( Char* bug_reports_to ); + +/* ------------------------------------------------------------------ */ +/* Needs */ + +/* Booleans that decide core behaviour, but don't require extra + operations to be defined if `True' */ + +/* Should __libc_freeres() be run? Bugs in it can crash the tool. */ +extern void VG_(needs_libc_freeres) ( void ); + +/* Want to have errors detected by Valgrind's core reported? Includes: + - pthread API errors (many; eg. unlocking a non-locked mutex) + - invalid file descriptors to blocking syscalls read() and write() + - bad signal numbers passed to sigaction() + - attempt to install signal handler for SIGKILL or SIGSTOP */ +extern void VG_(needs_core_errors) ( void ); + +/* Booleans that indicate extra operations are defined; if these are True, + the corresponding template functions (given below) must be defined. A + 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) ( + // 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 VG_(tdict).tool_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 + // VG_(tdict).tool_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 + // VG_(tdict).tool_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) ( + // 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) ( + // 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) ( + // 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? */ +// 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? */ +// Can be useful for ensuring a tool's correctness. cheap_sanity_check() +// is called very frequently; 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 ); + +/* Does the tool need shadow memory allocated? */ +extern void VG_(needs_shadow_memory)( void ); + +/* ------------------------------------------------------------------ */ +/* Malloc replacement */ + +// The 'p' prefix avoids GCC complaints about overshadowing global names. +extern void VG_(malloc_funcs)( + void* (*pmalloc) ( ThreadId tid, SizeT n ), + void* (*p__builtin_new) ( ThreadId tid, SizeT n ), + void* (*p__builtin_vec_new) ( ThreadId tid, SizeT n ), + void* (*pmemalign) ( ThreadId tid, SizeT align, SizeT n ), + void* (*pcalloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ), + void (*pfree) ( ThreadId tid, void* p ), + void (*p__builtin_delete) ( ThreadId tid, void* p ), + void (*p__builtin_vec_delete) ( ThreadId tid, void* p ), + void* (*prealloc) ( ThreadId tid, void* p, SizeT new_size ), + SizeT client_malloc_redzone_szB +); + +/* ------------------------------------------------------------------ */ +/* Core events to track */ + +/* Part of the core from which this call was made. Useful for determining + what kind of error message should be emitted. */ +typedef + enum { Vg_CoreStartup, Vg_CorePThread, Vg_CoreSignal, Vg_CoreSysCall, + Vg_CoreTranslate, Vg_CoreClientReq } + CorePart; + +/* Events happening in core to track. To be notified, pass a callback + function to the appropriate function. To ignore an event, don't do + anything (the default is for events to be ignored). + + Note that most events aren't passed a ThreadId. If the event is one called + from generated code (eg. new_mem_stack_*), you can use + VG_(get_running_tid)() to find it. Otherwise, it has to be passed in, + as in pre_mem_read, and so the event signature will require changing. + + Memory events (Nb: to track heap allocation/freeing, a tool must replace + malloc() et al. See above how to do this.) + + These ones occur at startup, upon some signals, and upon some syscalls + */ +void VG_(track_new_mem_startup) (void(*f)(Addr a, SizeT len, + Bool rr, Bool ww, Bool xx)); +void VG_(track_new_mem_stack_signal)(void(*f)(Addr a, SizeT len)); +void VG_(track_new_mem_brk) (void(*f)(Addr a, SizeT len)); +void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len, + Bool rr, Bool ww, Bool xx)); + +void VG_(track_copy_mem_remap) (void(*f)(Addr from, Addr to, SizeT len)); +void VG_(track_change_mem_mprotect) (void(*f)(Addr a, SizeT len, + Bool rr, Bool ww, Bool xx)); +void VG_(track_die_mem_stack_signal)(void(*f)(Addr a, SizeT len)); +void VG_(track_die_mem_brk) (void(*f)(Addr a, SizeT len)); +void VG_(track_die_mem_munmap) (void(*f)(Addr a, SizeT len)); + +/* These ones are called when SP changes. A tool could track these itself + (except for ban_mem_stack) but it's much easier to use the core's help. + + The specialised ones are called in preference to the general one, if they + are defined. These functions are called a lot if they are used, so + specialising can optimise things significantly. If any of the + specialised cases are defined, the general case must be defined too. + + Nb: all the specialised ones must use the VGA_REGPARM(n) attribute. + */ +void VG_(track_new_mem_stack_4) (VGA_REGPARM(1) void(*f)(Addr new_ESP)); +void VG_(track_new_mem_stack_8) (VGA_REGPARM(1) void(*f)(Addr new_ESP)); +void VG_(track_new_mem_stack_12)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); +void VG_(track_new_mem_stack_16)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); +void VG_(track_new_mem_stack_32)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); +void VG_(track_new_mem_stack) (void(*f)(Addr a, SizeT len)); + +void VG_(track_die_mem_stack_4) (VGA_REGPARM(1) void(*f)(Addr die_ESP)); +void VG_(track_die_mem_stack_8) (VGA_REGPARM(1) void(*f)(Addr die_ESP)); +void VG_(track_die_mem_stack_12)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); +void VG_(track_die_mem_stack_16)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); +void VG_(track_die_mem_stack_32)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); +void VG_(track_die_mem_stack) (void(*f)(Addr a, SizeT len)); + +/* Used for redzone at end of thread stacks */ +void VG_(track_ban_mem_stack) (void(*f)(Addr a, SizeT len)); + +/* These ones occur around syscalls, signal handling, etc */ +void VG_(track_pre_mem_read) (void(*f)(CorePart part, ThreadId tid, + Char* s, Addr a, SizeT size)); +void VG_(track_pre_mem_read_asciiz)(void(*f)(CorePart part, ThreadId tid, + Char* s, Addr a)); +void VG_(track_pre_mem_write) (void(*f)(CorePart part, ThreadId tid, + Char* s, Addr a, SizeT size)); +void VG_(track_post_mem_write) (void(*f)(CorePart part, ThreadId tid, + Addr a, SizeT size)); + +/* Register events. Use VG_(set_shadow_state_area)() to set the shadow regs + for these events. */ +void VG_(track_pre_reg_read) (void(*f)(CorePart part, ThreadId tid, + Char* s, OffT guest_state_offset, + SizeT size)); +void VG_(track_post_reg_write)(void(*f)(CorePart part, ThreadId tid, + OffT guest_state_offset, + SizeT size)); + +/* This one is called for malloc() et al if they are replaced by a tool. */ +void VG_(track_post_reg_write_clientcall_return)( + void(*f)(ThreadId tid, OffT guest_state_offset, SizeT size, Addr f)); + + +/* Scheduler events (not exhaustive) */ +void VG_(track_thread_run)(void(*f)(ThreadId tid)); + + +/* Thread events (not exhaustive) + + Called during thread create, before the new thread has run any + instructions (or touched any memory). + */ +void VG_(track_post_thread_create)(void(*f)(ThreadId tid, ThreadId child)); +void VG_(track_post_thread_join) (void(*f)(ThreadId joiner, ThreadId joinee)); + +/* Mutex events (not exhaustive) + "void *mutex" is really a pthread_mutex * + + Called before a thread can block while waiting for a mutex (called + regardless of whether the thread will block or not). */ +void VG_(track_pre_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); + +/* Called once the thread actually holds the mutex (always paired with + pre_mutex_lock). */ +void VG_(track_post_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); + +/* Called after a thread has released a mutex (no need for a corresponding + pre_mutex_unlock, because unlocking can't block). */ +void VG_(track_post_mutex_unlock)(void(*f)(ThreadId tid, void* mutex)); + +/* Signal events (not exhaustive) + + ... pre_send_signal, post_send_signal ... + + Called before a signal is delivered; `alt_stack' indicates if it is + delivered on an alternative stack. */ +void VG_(track_pre_deliver_signal) (void(*f)(ThreadId tid, Int sigNo, + Bool alt_stack)); +/* Called after a signal is delivered. Nb: unfortunately, if the signal + handler longjmps, this won't be called. */ +void VG_(track_post_deliver_signal)(void(*f)(ThreadId tid, Int sigNo)); + +/* Others... condition variables... + ... + Shadow memory management + */ +void VG_(track_init_shadow_page)(void(*f)(Addr p)); + +#endif // __PUB_TOOL_TOOLIFACE_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/include/tool.h b/include/tool.h index 39caa89b99..5f5b7897d6 100644 --- a/include/tool.h +++ b/include/tool.h @@ -73,46 +73,6 @@ extern const Char *VG_(libdir); -/*====================================================================*/ -/*=== Core/tool interface version ===*/ -/*====================================================================*/ - -/* The version number indicates binary-incompatible changes to the - interface; if the core and tool versions don't match, Valgrind - will abort. */ -#define VG_CORE_INTERFACE_VERSION 8 - -typedef struct _ToolInfo { - Int sizeof_ToolInfo; - Int interface_version; - - /* Initialise tool. Must do the following: - - initialise the `details' struct, via the VG_(details_*)() functions - - register any helpers called by generated code - - May do the following: - - initialise the `needs' struct to indicate certain requirements, via - the VG_(needs_*)() functions - - initialize all the tool's entrypoints via the VG_(init_*)() functions - - register any tool-specific profiling events - - any other tool-specific initialisation - */ - void (*tl_pre_clo_init) ( void ); - - /* Specifies how big the shadow segment should be as a ratio to the - client address space. 0 for no shadow segment. */ - float shadow_ratio; -} ToolInfo; - -/* Every tool must include this macro somewhere, exactly once. */ -#define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init, shadow) \ - const ToolInfo VG_(tool_info) = { \ - .sizeof_ToolInfo = sizeof(ToolInfo), \ - .interface_version = VG_CORE_INTERFACE_VERSION, \ - .tl_pre_clo_init = pre_clo_init, \ - .shadow_ratio = shadow, \ - }; - /*====================================================================*/ /*=== Command-line options ===*/ /*====================================================================*/ @@ -776,343 +736,6 @@ extern void VG_(get_shadow_regs_area) ( ThreadId tid, OffT guest_state_offset, extern void VG_(set_shadow_regs_area) ( ThreadId tid, OffT guest_state_offset, SizeT size, const UChar* area ); -/*====================================================================*/ -/*=== Tool-specific stuff ===*/ -/*====================================================================*/ - -/* ------------------------------------------------------------------ */ -/* Basic tool functions */ - -extern void VG_(basic_tool_funcs)( - // Do any initialisation that can only be done after command line - // processing. - void (*post_clo_init)(void), - - // Instrument a basic block. Must be a true function, ie. the same input - // always results in the same output, because basic blocks can be - // retranslated. Unless you're doing something really strange... - IRBB* (*instrument)(IRBB* bb_in, VexGuestLayout* layout, - IRType gWordTy, IRType hWordTy ), - - // Finish up, print out any results, etc. `exitcode' is program's exit - // code. The shadow can be found with VG_(get_exit_status_shadow)(). - void (*fini)(Int) -); - -/* ------------------------------------------------------------------ */ -/* Details */ - -/* Default value for avg_translations_sizeB (in bytes), indicating typical - code expansion of about 6:1. */ -#define VG_DEFAULT_TRANS_SIZEB 100 - -/* Information used in the startup message. `name' also determines the - string used for identifying suppressions in a suppression file as - belonging to this tool. `version' can be NULL, in which case (not - surprisingly) no version info is printed; this mechanism is designed for - tools distributed with Valgrind that share a version number with - Valgrind. Other tools not distributed as part of Valgrind should - probably have their own version number. */ -extern void VG_(details_name) ( Char* name ); -extern void VG_(details_version) ( Char* version ); -extern void VG_(details_description) ( Char* description ); -extern void VG_(details_copyright_author) ( Char* copyright_author ); - -/* Average size of a translation, in bytes, so that the translation - storage machinery can allocate memory appropriately. Not critical, - setting is optional. */ -extern void VG_(details_avg_translation_sizeB) ( UInt size ); - -/* String printed if an `tl_assert' assertion fails or VG_(tool_panic) - is called. Should probably be an email address. */ -extern void VG_(details_bug_reports_to) ( Char* bug_reports_to ); - -/* ------------------------------------------------------------------ */ -/* Needs */ - -/* Booleans that decide core behaviour, but don't require extra - operations to be defined if `True' */ - -/* Should __libc_freeres() be run? Bugs in it can crash the tool. */ -extern void VG_(needs_libc_freeres) ( void ); - -/* Want to have errors detected by Valgrind's core reported? Includes: - - pthread API errors (many; eg. unlocking a non-locked mutex) - - invalid file descriptors to blocking syscalls read() and write() - - bad signal numbers passed to sigaction() - - attempt to install signal handler for SIGKILL or SIGSTOP */ -extern void VG_(needs_core_errors) ( void ); - -/* Booleans that indicate extra operations are defined; if these are True, - the corresponding template functions (given below) must be defined. A - 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) ( - // 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 VG_(tdict).tool_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 - // VG_(tdict).tool_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 - // VG_(tdict).tool_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) ( - // 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) ( - // 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) ( - // 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? */ -// 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? */ -// Can be useful for ensuring a tool's correctness. cheap_sanity_check() -// is called very frequently; 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 ); - -/* Does the tool need shadow memory allocated? */ -extern void VG_(needs_shadow_memory)( void ); - -/* ------------------------------------------------------------------ */ -/* Malloc replacement */ - -// The 'p' prefix avoids GCC complaints about overshadowing global names. -extern void VG_(malloc_funcs)( - void* (*pmalloc) ( ThreadId tid, SizeT n ), - void* (*p__builtin_new) ( ThreadId tid, SizeT n ), - void* (*p__builtin_vec_new) ( ThreadId tid, SizeT n ), - void* (*pmemalign) ( ThreadId tid, SizeT align, SizeT n ), - void* (*pcalloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ), - void (*pfree) ( ThreadId tid, void* p ), - void (*p__builtin_delete) ( ThreadId tid, void* p ), - void (*p__builtin_vec_delete) ( ThreadId tid, void* p ), - void* (*prealloc) ( ThreadId tid, void* p, SizeT new_size ), - SizeT client_malloc_redzone_szB -); - -/* ------------------------------------------------------------------ */ -/* Core events to track */ - -/* Part of the core from which this call was made. Useful for determining - what kind of error message should be emitted. */ -typedef - enum { Vg_CoreStartup, Vg_CorePThread, Vg_CoreSignal, Vg_CoreSysCall, - Vg_CoreTranslate, Vg_CoreClientReq } - CorePart; - -/* Events happening in core to track. To be notified, pass a callback - function to the appropriate function. To ignore an event, don't do - anything (the default is for events to be ignored). - - Note that most events aren't passed a ThreadId. If the event is one called - from generated code (eg. new_mem_stack_*), you can use - VG_(get_running_tid)() to find it. Otherwise, it has to be passed in, - as in pre_mem_read, and so the event signature will require changing. - - Memory events (Nb: to track heap allocation/freeing, a tool must replace - malloc() et al. See above how to do this.) - - These ones occur at startup, upon some signals, and upon some syscalls - */ -void VG_(track_new_mem_startup) (void(*f)(Addr a, SizeT len, - Bool rr, Bool ww, Bool xx)); -void VG_(track_new_mem_stack_signal)(void(*f)(Addr a, SizeT len)); -void VG_(track_new_mem_brk) (void(*f)(Addr a, SizeT len)); -void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len, - Bool rr, Bool ww, Bool xx)); - -void VG_(track_copy_mem_remap) (void(*f)(Addr from, Addr to, SizeT len)); -void VG_(track_change_mem_mprotect) (void(*f)(Addr a, SizeT len, - Bool rr, Bool ww, Bool xx)); -void VG_(track_die_mem_stack_signal)(void(*f)(Addr a, SizeT len)); -void VG_(track_die_mem_brk) (void(*f)(Addr a, SizeT len)); -void VG_(track_die_mem_munmap) (void(*f)(Addr a, SizeT len)); - -/* These ones are called when SP changes. A tool could track these itself - (except for ban_mem_stack) but it's much easier to use the core's help. - - The specialised ones are called in preference to the general one, if they - are defined. These functions are called a lot if they are used, so - specialising can optimise things significantly. If any of the - specialised cases are defined, the general case must be defined too. - - Nb: all the specialised ones must use the VGA_REGPARM(n) attribute. - */ -void VG_(track_new_mem_stack_4) (VGA_REGPARM(1) void(*f)(Addr new_ESP)); -void VG_(track_new_mem_stack_8) (VGA_REGPARM(1) void(*f)(Addr new_ESP)); -void VG_(track_new_mem_stack_12)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); -void VG_(track_new_mem_stack_16)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); -void VG_(track_new_mem_stack_32)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); -void VG_(track_new_mem_stack) (void(*f)(Addr a, SizeT len)); - -void VG_(track_die_mem_stack_4) (VGA_REGPARM(1) void(*f)(Addr die_ESP)); -void VG_(track_die_mem_stack_8) (VGA_REGPARM(1) void(*f)(Addr die_ESP)); -void VG_(track_die_mem_stack_12)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); -void VG_(track_die_mem_stack_16)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); -void VG_(track_die_mem_stack_32)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); -void VG_(track_die_mem_stack) (void(*f)(Addr a, SizeT len)); - -/* Used for redzone at end of thread stacks */ -void VG_(track_ban_mem_stack) (void(*f)(Addr a, SizeT len)); - -/* These ones occur around syscalls, signal handling, etc */ -void VG_(track_pre_mem_read) (void(*f)(CorePart part, ThreadId tid, - Char* s, Addr a, SizeT size)); -void VG_(track_pre_mem_read_asciiz)(void(*f)(CorePart part, ThreadId tid, - Char* s, Addr a)); -void VG_(track_pre_mem_write) (void(*f)(CorePart part, ThreadId tid, - Char* s, Addr a, SizeT size)); -void VG_(track_post_mem_write) (void(*f)(CorePart part, ThreadId tid, - Addr a, SizeT size)); - -/* Register events. Use VG_(set_shadow_state_area)() to set the shadow regs - for these events. */ -void VG_(track_pre_reg_read) (void(*f)(CorePart part, ThreadId tid, - Char* s, OffT guest_state_offset, - SizeT size)); -void VG_(track_post_reg_write)(void(*f)(CorePart part, ThreadId tid, - OffT guest_state_offset, - SizeT size)); - -/* This one is called for malloc() et al if they are replaced by a tool. */ -void VG_(track_post_reg_write_clientcall_return)( - void(*f)(ThreadId tid, OffT guest_state_offset, SizeT size, Addr f)); - - -/* Scheduler events (not exhaustive) */ -void VG_(track_thread_run)(void(*f)(ThreadId tid)); - - -/* Thread events (not exhaustive) - - Called during thread create, before the new thread has run any - instructions (or touched any memory). - */ -void VG_(track_post_thread_create)(void(*f)(ThreadId tid, ThreadId child)); -void VG_(track_post_thread_join) (void(*f)(ThreadId joiner, ThreadId joinee)); - -/* Mutex events (not exhaustive) - "void *mutex" is really a pthread_mutex * - - Called before a thread can block while waiting for a mutex (called - regardless of whether the thread will block or not). */ -void VG_(track_pre_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); - -/* Called once the thread actually holds the mutex (always paired with - pre_mutex_lock). */ -void VG_(track_post_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); - -/* Called after a thread has released a mutex (no need for a corresponding - pre_mutex_unlock, because unlocking can't block). */ -void VG_(track_post_mutex_unlock)(void(*f)(ThreadId tid, void* mutex)); - -/* Signal events (not exhaustive) - - ... pre_send_signal, post_send_signal ... - - Called before a signal is delivered; `alt_stack' indicates if it is - delivered on an alternative stack. */ -void VG_(track_pre_deliver_signal) (void(*f)(ThreadId tid, Int sigNo, - Bool alt_stack)); -/* Called after a signal is delivered. Nb: unfortunately, if the signal - handler longjmps, this won't be called. */ -void VG_(track_post_deliver_signal)(void(*f)(ThreadId tid, Int sigNo)); - - -/* Others... condition variables... - ... - - Shadow memory management - */ -void VG_(track_init_shadow_page)(void(*f)(Addr p)); - #endif /* __TOOL_H */ diff --git a/lackey/lk_main.c b/lackey/lk_main.c index 4657340d21..80a987b63a 100644 --- a/lackey/lk_main.c +++ b/lackey/lk_main.c @@ -30,6 +30,7 @@ */ #include "tool.h" +#include "pub_tool_tooliface.h" /* Nb: use ULongs because the numbers can get very big */ static ULong n_dlrr_calls = 0; diff --git a/massif/ms_main.c b/massif/ms_main.c index df2ca807b8..55be3c2ac0 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -38,6 +38,7 @@ #include "pub_tool_mallocfree.h" #include "pub_tool_replacemalloc.h" #include "pub_tool_stacktrace.h" +#include "pub_tool_tooliface.h" #include "valgrind.h" // For {MALLOC,FREE}LIKE_BLOCK diff --git a/memcheck/mac_shared.h b/memcheck/mac_shared.h index 82303e8e95..186021d4dc 100644 --- a/memcheck/mac_shared.h +++ b/memcheck/mac_shared.h @@ -39,6 +39,7 @@ #include "tool.h" #include "pub_tool_mallocfree.h" #include "pub_tool_replacemalloc.h" +#include "pub_tool_tooliface.h" #define MAC_(str) VGAPPEND(vgMAC_,str) diff --git a/none/nl_main.c b/none/nl_main.c index 63d2fe0219..c2e680ba4d 100644 --- a/none/nl_main.c +++ b/none/nl_main.c @@ -29,6 +29,7 @@ */ #include "tool.h" +#include "pub_tool_tooliface.h" static void nl_post_clo_init(void) {