diff options
author | Stephane Marchesin <marchesin@icps.u-strasbg.fr> | 2009-05-04 19:05:59 +0200 |
---|---|---|
committer | Stephane Marchesin <marchesin@icps.u-strasbg.fr> | 2009-05-04 19:05:59 +0200 |
commit | 6e410b3bb6ff51580897431105aae14591cbf7fb (patch) | |
tree | f8aeba9352710f10cd6b1d5138c8fc3ece91c8c3 /coregrind/m_tooliface.c |
Diffstat (limited to 'coregrind/m_tooliface.c')
-rw-r--r-- | coregrind/m_tooliface.c | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c new file mode 100644 index 0000000..79a5e4b --- /dev/null +++ b/coregrind/m_tooliface.c @@ -0,0 +1,413 @@ + +/*--------------------------------------------------------------------*/ +/*--- Stuff relating to tool data structures. ---*/ +/*--- m_tooliface.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 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 "pub_core_basics.h" +#include "pub_core_tooliface.h" + +// The core/tool dictionary of functions (initially zeroed, as we want it) +VgToolInterface VG_(tdict); + +/*--------------------------------------------------------------------*/ +/* Setting basic functions */ + +void VG_(basic_tool_funcs)( + void(*post_clo_init)(void), + IRSB*(*instrument)(VgCallbackClosure*, IRSB*, + VexGuestLayout*, VexGuestExtents*, IRType, IRType), + void(*fini)(Int) +) +{ + VG_(tdict).tool_post_clo_init = post_clo_init; + VG_(tdict).tool_instrument = instrument; + VG_(tdict).tool_fini = fini; +} + + +/*--------------------------------------------------------------------*/ +/* Setting details */ + +/* Init with default values. */ +VgDetails VG_(details) = { + .name = NULL, + .version = NULL, + .description = NULL, + .copyright_author = NULL, + .bug_reports_to = NULL, + .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, + .libc_freeres = False, + .superblock_discards = False, + .command_line_options = False, + .client_requests = False, + .syscall_wrapper = False, + .sanity_checks = False, + .var_info = False, + .malloc_replacement = False, + .xml_output = False, + .final_IR_tidy_pass = False +}; + +/* static */ +Bool VG_(sanity_check_needs)(Char** failmsg) +{ + Bool any_new_mem_stack_N, any_new_mem_stack_N_w_ECU; + Bool any_new_mem_stack_w_conflicting_otags; + Bool any_die_mem_stack_N; + +#define CHECK_NOT(var, value) \ + if ((var)==(value)) { \ + *failmsg = "Tool error: '" #var "' not initialised\n"; \ + return False; \ + } + + /* Ones that must be set */ + CHECK_NOT(VG_(details).name, NULL); + /* Nb: .version can be NULL */ + CHECK_NOT(VG_(details).description, NULL); + CHECK_NOT(VG_(details).copyright_author, NULL); + CHECK_NOT(VG_(details).bug_reports_to, NULL); + + /* Check that new_mem_stack is defined if any new_mem_stack_N + are. */ + any_new_mem_stack_N + = VG_(tdict).track_new_mem_stack_4 || + VG_(tdict).track_new_mem_stack_8 || + VG_(tdict).track_new_mem_stack_12 || + VG_(tdict).track_new_mem_stack_16 || + VG_(tdict).track_new_mem_stack_32 || + VG_(tdict).track_new_mem_stack_112 || + VG_(tdict).track_new_mem_stack_128 || + VG_(tdict).track_new_mem_stack_144 || + VG_(tdict).track_new_mem_stack_160; + + if (any_new_mem_stack_N && ! VG_(tdict).track_new_mem_stack) { + *failmsg = "Tool error: one of the specialised 'new_mem_stack_N'\n" + " events tracked, but not the generic 'new_mem_stack' one.\n" + " 'new_mem_stack' should be defined\n"; + return False; + } + + /* Check that new_mem_stack_w_ECU is defined if any + new_mem_stack_N_w_ECU are. */ + any_new_mem_stack_N_w_ECU + = VG_(tdict).track_new_mem_stack_4_w_ECU || + VG_(tdict).track_new_mem_stack_8_w_ECU || + VG_(tdict).track_new_mem_stack_12_w_ECU || + VG_(tdict).track_new_mem_stack_16_w_ECU || + VG_(tdict).track_new_mem_stack_32_w_ECU || + VG_(tdict).track_new_mem_stack_112_w_ECU || + VG_(tdict).track_new_mem_stack_128_w_ECU || + VG_(tdict).track_new_mem_stack_144_w_ECU || + VG_(tdict).track_new_mem_stack_160_w_ECU; + + if (any_new_mem_stack_N_w_ECU && ! VG_(tdict).track_new_mem_stack_w_ECU) { + *failmsg = "Tool error: one of the specialised 'new_mem_stack_N_w_ECU'\n" + " events tracked, but not the generic 'new_mem_stack_w_ECU' one.\n" + " 'new_mem_stack_w_ECU' should be defined\n"; + return False; + } + + /* Check that in no cases are both with- and without-otag versions of the + same new_mem_stack_ function defined. */ + any_new_mem_stack_w_conflicting_otags + = (VG_(tdict).track_new_mem_stack_4 && VG_(tdict).track_new_mem_stack_4_w_ECU) || + (VG_(tdict).track_new_mem_stack_8 && VG_(tdict).track_new_mem_stack_8_w_ECU) || + (VG_(tdict).track_new_mem_stack_12 && VG_(tdict).track_new_mem_stack_12_w_ECU) || + (VG_(tdict).track_new_mem_stack_16 && VG_(tdict).track_new_mem_stack_16_w_ECU) || + (VG_(tdict).track_new_mem_stack_32 && VG_(tdict).track_new_mem_stack_32_w_ECU) || + (VG_(tdict).track_new_mem_stack_112 && VG_(tdict).track_new_mem_stack_112_w_ECU) || + (VG_(tdict).track_new_mem_stack_128 && VG_(tdict).track_new_mem_stack_128_w_ECU) || + (VG_(tdict).track_new_mem_stack_144 && VG_(tdict).track_new_mem_stack_144_w_ECU) || + (VG_(tdict).track_new_mem_stack_160 && VG_(tdict).track_new_mem_stack_160_w_ECU) || + (VG_(tdict).track_new_mem_stack && VG_(tdict).track_new_mem_stack_w_ECU); + + if (any_new_mem_stack_w_conflicting_otags) { + *failmsg = "Tool error: tool supplies both a 'new_mem_stack_N' and a\n" + " 'new_mem_stack_N_w_ECU' function for some N (or none),\n" + " but you can only have one or the other (not both)\n"; + return False; + } + + /* Check that die_mem_stack is defined if any die_mem_stack_N + are. */ + any_die_mem_stack_N + = VG_(tdict).track_die_mem_stack_4 || + VG_(tdict).track_die_mem_stack_8 || + VG_(tdict).track_die_mem_stack_12 || + VG_(tdict).track_die_mem_stack_16 || + VG_(tdict).track_die_mem_stack_32 || + VG_(tdict).track_die_mem_stack_112 || + VG_(tdict).track_die_mem_stack_128 || + VG_(tdict).track_die_mem_stack_144 || + VG_(tdict).track_die_mem_stack_160; + + if (any_die_mem_stack_N && ! VG_(tdict).track_die_mem_stack) { + *failmsg = "Tool error: one of the specialised 'die_mem_stack_N'\n" + " events tracked, but not the generic 'die_mem_stack' one.\n" + " 'die_mem_stack' should be defined\n"; + return False; + } + + return True; + +#undef CHECK_NOT +} + +/* 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(var_info) +NEEDS(xml_output) + +void VG_(needs_superblock_discards)( + void (*discard)(Addr64, VexGuestExtents) +) +{ + VG_(needs).superblock_discards = True; + VG_(tdict).tool_discard_superblock_info = discard; +} + +void VG_(needs_tool_errors)( + Bool (*eq) (VgRes, Error*, Error*), + void (*pp) (Error*), + Bool show_TIDs, + 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_(tdict).tool_eq_Error = eq; + VG_(tdict).tool_pp_Error = pp; + VG_(tdict).tool_show_ThreadIDs_for_errors = show_TIDs; + VG_(tdict).tool_update_extra = update; + VG_(tdict).tool_recognised_suppression = recog; + VG_(tdict).tool_read_extra_suppression_info = read_extra; + VG_(tdict).tool_error_matches_suppression = matches; + VG_(tdict).tool_get_error_name = name; + VG_(tdict).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_(tdict).tool_process_cmd_line_option = process; + VG_(tdict).tool_print_usage = usage; + VG_(tdict).tool_print_debug_usage = debug_usage; +} + +void VG_(needs_client_requests)( + Bool (*handle)(ThreadId, UWord*, UWord*) +) +{ + VG_(needs).client_requests = True; + VG_(tdict).tool_handle_client_request = handle; +} + +void VG_(needs_syscall_wrapper)( + void(*pre) (ThreadId, UInt), + void(*post)(ThreadId, UInt, SysRes res) +) +{ + VG_(needs).syscall_wrapper = True; + VG_(tdict).tool_pre_syscall = pre; + VG_(tdict).tool_post_syscall = post; +} + +void VG_(needs_sanity_checks)( + Bool(*cheap)(void), + Bool(*expen)(void) +) +{ + VG_(needs).sanity_checks = True; + VG_(tdict).tool_cheap_sanity_check = cheap; + VG_(tdict).tool_expensive_sanity_check = expen; +} + +void VG_(needs_malloc_replacement)( + 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 ), + SizeT (*malloc_usable_size) ( ThreadId, void* ), + SizeT client_malloc_redzone_szB +) +{ + VG_(needs).malloc_replacement = True; + VG_(tdict).tool_malloc = malloc; + VG_(tdict).tool___builtin_new = __builtin_new; + VG_(tdict).tool___builtin_vec_new = __builtin_vec_new; + VG_(tdict).tool_memalign = memalign; + VG_(tdict).tool_calloc = calloc; + VG_(tdict).tool_free = free; + VG_(tdict).tool___builtin_delete = __builtin_delete; + VG_(tdict).tool___builtin_vec_delete = __builtin_vec_delete; + VG_(tdict).tool_realloc = realloc; + VG_(tdict).tool_malloc_usable_size = malloc_usable_size; + VG_(tdict).tool_client_redzone_szB = client_malloc_redzone_szB; +} + +void VG_(needs_final_IR_tidy_pass)( + IRSB*(*final_tidy)(IRSB*) +) +{ + VG_(needs).final_IR_tidy_pass = True; + VG_(tdict).tool_final_IR_tidy_pass = final_tidy; +} + +/*--------------------------------------------------------------------*/ +/* Tracked events. Digit 'n' on DEFn is the REGPARMness. */ + +#define DEF0(fn, args...) \ +void VG_(fn)(void(*f)(args)) { \ + VG_(tdict).fn = f; \ +} + +#define DEF1(fn, args...) \ +void VG_(fn)(VG_REGPARM(1) void(*f)(args)) { \ + VG_(tdict).fn = f; \ +} + +#define DEF2(fn, args...) \ +void VG_(fn)(VG_REGPARM(2) void(*f)(args)) { \ + VG_(tdict).fn = f; \ +} + +DEF0(track_new_mem_startup, Addr, SizeT, Bool, Bool, Bool, ULong) +DEF0(track_new_mem_stack_signal, Addr, SizeT, UInt) +DEF0(track_new_mem_brk, Addr, SizeT, UInt) +DEF0(track_new_mem_mmap, Addr, SizeT, Bool, Bool, Bool, ULong) + +DEF0(track_copy_mem_remap, Addr, Addr, SizeT) +DEF0(track_change_mem_mprotect, Addr, SizeT, Bool, Bool, Bool) +DEF0(track_die_mem_stack_signal, Addr, SizeT) +DEF0(track_die_mem_brk, Addr, SizeT) +DEF0(track_die_mem_munmap, Addr, SizeT) + +DEF2(track_new_mem_stack_4_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_8_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_12_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_16_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_32_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_112_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_128_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_144_w_ECU, Addr, UInt) +DEF2(track_new_mem_stack_160_w_ECU, Addr, UInt) +DEF0(track_new_mem_stack_w_ECU, Addr, SizeT, UInt) + +DEF1(track_new_mem_stack_4, Addr) +DEF1(track_new_mem_stack_8, Addr) +DEF1(track_new_mem_stack_12, Addr) +DEF1(track_new_mem_stack_16, Addr) +DEF1(track_new_mem_stack_32, Addr) +DEF1(track_new_mem_stack_112, Addr) +DEF1(track_new_mem_stack_128, Addr) +DEF1(track_new_mem_stack_144, Addr) +DEF1(track_new_mem_stack_160, Addr) +DEF0(track_new_mem_stack, Addr, SizeT) + +DEF1(track_die_mem_stack_4, Addr) +DEF1(track_die_mem_stack_8, Addr) +DEF1(track_die_mem_stack_12, Addr) +DEF1(track_die_mem_stack_16, Addr) +DEF1(track_die_mem_stack_32, Addr) +DEF1(track_die_mem_stack_112, Addr) +DEF1(track_die_mem_stack_128, Addr) +DEF1(track_die_mem_stack_144, Addr) +DEF1(track_die_mem_stack_160, Addr) +DEF0(track_die_mem_stack, Addr, SizeT) + +DEF0(track_ban_mem_stack, Addr, SizeT) + +DEF0(track_pre_mem_read, CorePart, ThreadId, Char*, Addr, SizeT) +DEF0(track_pre_mem_read_asciiz, CorePart, ThreadId, Char*, Addr) +DEF0(track_pre_mem_write, CorePart, ThreadId, Char*, Addr, SizeT) +DEF0(track_post_mem_write, CorePart, ThreadId, Addr, SizeT) + +DEF0(track_pre_reg_read, CorePart, ThreadId, Char*, PtrdiffT, SizeT) +DEF0(track_post_reg_write, CorePart, ThreadId, PtrdiffT, SizeT) + +DEF0(track_post_reg_write_clientcall_return, ThreadId, PtrdiffT, SizeT, Addr) + +DEF0(track_start_client_code, ThreadId, ULong) +DEF0(track_stop_client_code, ThreadId, ULong) + +DEF0(track_pre_thread_ll_create, ThreadId, ThreadId) +DEF0(track_pre_thread_first_insn, ThreadId) +DEF0(track_pre_thread_ll_exit, ThreadId) + +DEF0(track_pre_deliver_signal, ThreadId, Int sigNo, Bool) +DEF0(track_post_deliver_signal, ThreadId, Int sigNo) + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ |