njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
nethercote | 7cc9c23 | 2004-01-21 15:08:04 +0000 | [diff] [blame] | 3 | /*--- Stuff relating to tool data structures. ---*/ |
sewardj | a765834 | 2005-05-17 13:43:54 +0000 | [diff] [blame] | 4 | /*--- m_tooliface.c ---*/ |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 5 | /*--------------------------------------------------------------------*/ |
| 6 | |
| 7 | /* |
njn | b9c427c | 2004-12-01 14:14:42 +0000 | [diff] [blame] | 8 | This file is part of Valgrind, a dynamic binary instrumentation |
| 9 | framework. |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 10 | |
njn | 5361242 | 2005-03-12 16:22:54 +0000 | [diff] [blame] | 11 | Copyright (C) 2000-2005 Nicholas Nethercote |
njn | 2bc1012 | 2005-05-08 02:10:27 +0000 | [diff] [blame] | 12 | njn@valgrind.org |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 13 | |
| 14 | This program is free software; you can redistribute it and/or |
| 15 | modify it under the terms of the GNU General Public License as |
| 16 | published by the Free Software Foundation; either version 2 of the |
| 17 | License, or (at your option) any later version. |
| 18 | |
| 19 | This program is distributed in the hope that it will be useful, but |
| 20 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 22 | General Public License for more details. |
| 23 | |
| 24 | You should have received a copy of the GNU General Public License |
| 25 | along with this program; if not, write to the Free Software |
| 26 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 27 | 02111-1307, USA. |
| 28 | |
| 29 | The GNU General Public License is contained in the file COPYING. |
| 30 | */ |
| 31 | |
njn | c7561b9 | 2005-06-19 01:24:32 +0000 | [diff] [blame] | 32 | #include "pub_core_basics.h" |
njn | 4802b38 | 2005-06-11 04:58:29 +0000 | [diff] [blame] | 33 | #include "pub_core_tooliface.h" |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 34 | |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 35 | // The core/tool dictionary of functions (initially zeroed, as we want it) |
| 36 | VgToolInterface VG_(tdict); |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 37 | |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 38 | /*--------------------------------------------------------------------*/ |
| 39 | /* Setting basic functions */ |
| 40 | |
| 41 | void VG_(basic_tool_funcs)( |
| 42 | void(*post_clo_init)(void), |
sewardj | 4ba057c | 2005-10-18 12:04:18 +0000 | [diff] [blame] | 43 | IRBB*(*instrument)(IRBB*, VexGuestLayout*, |
| 44 | Addr64, VexGuestExtents*, IRType, IRType ), |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 45 | void(*fini)(Int) |
| 46 | ) |
| 47 | { |
njn | cf81d55 | 2005-03-31 04:52:26 +0000 | [diff] [blame] | 48 | VG_(tdict).tool_post_clo_init = post_clo_init; |
| 49 | VG_(tdict).tool_instrument = instrument; |
| 50 | VG_(tdict).tool_fini = fini; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 51 | } |
| 52 | |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 53 | |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 54 | /*--------------------------------------------------------------------*/ |
| 55 | /* Setting details */ |
| 56 | |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 57 | /* Init with default values. */ |
| 58 | VgDetails VG_(details) = { |
sewardj | c0d8f68 | 2002-11-30 00:49:43 +0000 | [diff] [blame] | 59 | .name = NULL, |
| 60 | .version = NULL, |
| 61 | .description = NULL, |
| 62 | .copyright_author = NULL, |
| 63 | .bug_reports_to = NULL, |
njn | 120281f | 2003-02-03 12:20:07 +0000 | [diff] [blame] | 64 | .avg_translation_sizeB = VG_DEFAULT_TRANS_SIZEB, |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 65 | }; |
| 66 | |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 67 | /* Use macro because they're so repetitive */ |
| 68 | #define DETAILS(type, detail) \ |
| 69 | extern void VG_(details_##detail)(type detail) \ |
| 70 | { \ |
| 71 | VG_(details).detail = detail; \ |
| 72 | } |
| 73 | |
| 74 | DETAILS(Char*, name) |
| 75 | DETAILS(Char*, version) |
| 76 | DETAILS(Char*, description) |
| 77 | DETAILS(Char*, copyright_author) |
| 78 | DETAILS(Char*, bug_reports_to) |
| 79 | DETAILS(UInt, avg_translation_sizeB) |
| 80 | |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 81 | |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 82 | /*--------------------------------------------------------------------*/ |
| 83 | /* Setting needs */ |
| 84 | |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 85 | VgNeeds VG_(needs) = { |
| 86 | .core_errors = False, |
njn | 95ec870 | 2004-11-22 16:46:13 +0000 | [diff] [blame] | 87 | .tool_errors = False, |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 88 | .libc_freeres = False, |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 89 | .basic_block_discards = False, |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 90 | .command_line_options = False, |
| 91 | .client_requests = False, |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 92 | .syscall_wrapper = False, |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 93 | .sanity_checks = False, |
| 94 | .data_syms = False, |
njn | fc51f8d | 2005-06-21 03:20:17 +0000 | [diff] [blame] | 95 | .malloc_replacement = False, |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 96 | }; |
| 97 | |
| 98 | /* static */ |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 99 | Bool VG_(sanity_check_needs)(Char** failmsg) |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 100 | { |
njn | 64c8324 | 2005-06-21 01:54:38 +0000 | [diff] [blame] | 101 | #define CHECK_NOT(var, value) \ |
| 102 | if ((var)==(value)) { \ |
| 103 | *failmsg = "Tool error: '" #var "' not initialised\n"; \ |
| 104 | return False; \ |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 105 | } |
| 106 | |
njn | 120281f | 2003-02-03 12:20:07 +0000 | [diff] [blame] | 107 | /* Ones that must be set */ |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 108 | CHECK_NOT(VG_(details).name, NULL); |
| 109 | /* Nb: .version can be NULL */ |
| 110 | CHECK_NOT(VG_(details).description, NULL); |
| 111 | CHECK_NOT(VG_(details).copyright_author, NULL); |
| 112 | CHECK_NOT(VG_(details).bug_reports_to, NULL); |
| 113 | |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 114 | if ( (VG_(tdict).track_new_mem_stack_4 || |
| 115 | VG_(tdict).track_new_mem_stack_8 || |
| 116 | VG_(tdict).track_new_mem_stack_12 || |
| 117 | VG_(tdict).track_new_mem_stack_16 || |
| 118 | VG_(tdict).track_new_mem_stack_32 ) && |
| 119 | ! VG_(tdict).track_new_mem_stack) |
njn | d304045 | 2003-05-19 15:04:06 +0000 | [diff] [blame] | 120 | { |
njn | 64c8324 | 2005-06-21 01:54:38 +0000 | [diff] [blame] | 121 | *failmsg = "Tool error: one of the specialised 'new_mem_stack_n'\n" |
| 122 | " events tracked, but not the generic 'new_mem_stack' one.\n" |
| 123 | " 'new_mem_stack' should be defined\n"; |
| 124 | return False; |
njn | 9b007f6 | 2003-04-07 14:40:25 +0000 | [diff] [blame] | 125 | } |
| 126 | |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 127 | if ( (VG_(tdict).track_die_mem_stack_4 || |
| 128 | VG_(tdict).track_die_mem_stack_8 || |
| 129 | VG_(tdict).track_die_mem_stack_12 || |
| 130 | VG_(tdict).track_die_mem_stack_16 || |
| 131 | VG_(tdict).track_die_mem_stack_32 ) && |
| 132 | ! VG_(tdict).track_die_mem_stack) |
njn | d304045 | 2003-05-19 15:04:06 +0000 | [diff] [blame] | 133 | { |
njn | 64c8324 | 2005-06-21 01:54:38 +0000 | [diff] [blame] | 134 | *failmsg = "Tool error: one of the specialised 'die_mem_stack_n'\n" |
| 135 | " events tracked, but not the generic 'die_mem_stack' one.\n" |
| 136 | " 'die_mem_stack' should be defined\n"; |
| 137 | return False; |
njn | 9b007f6 | 2003-04-07 14:40:25 +0000 | [diff] [blame] | 138 | } |
| 139 | |
njn | 64c8324 | 2005-06-21 01:54:38 +0000 | [diff] [blame] | 140 | return True; |
| 141 | |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 142 | #undef CHECK_NOT |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 143 | } |
| 144 | |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 145 | /* Use macro because they're so repetitive */ |
| 146 | #define NEEDS(need) \ |
| 147 | extern void VG_(needs_##need)(void) \ |
| 148 | { \ |
| 149 | VG_(needs).need = True; \ |
| 150 | } |
| 151 | |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 152 | // These ones don't require any tool-supplied functions |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 153 | NEEDS(libc_freeres) |
| 154 | NEEDS(core_errors) |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 155 | NEEDS(data_syms) |
njn | fdc28af | 2003-02-24 10:36:48 +0000 | [diff] [blame] | 156 | |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 157 | void VG_(needs_basic_block_discards)( |
sewardj | 4ba057c | 2005-10-18 12:04:18 +0000 | [diff] [blame] | 158 | void (*discard)(Addr64, VexGuestExtents) |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 159 | ) |
| 160 | { |
| 161 | VG_(needs).basic_block_discards = True; |
njn | cf81d55 | 2005-03-31 04:52:26 +0000 | [diff] [blame] | 162 | VG_(tdict).tool_discard_basic_block_info = discard; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | void VG_(needs_tool_errors)( |
| 166 | Bool (*eq) (VgRes, Error*, Error*), |
| 167 | void (*pp) (Error*), |
| 168 | UInt (*update) (Error*), |
| 169 | Bool (*recog) (Char*, Supp*), |
| 170 | Bool (*read_extra) (Int, Char*, Int, Supp*), |
| 171 | Bool (*matches) (Error*, Supp*), |
| 172 | Char* (*name) (Error*), |
| 173 | void (*print_extra)(Error*) |
| 174 | ) |
| 175 | { |
| 176 | VG_(needs).tool_errors = True; |
njn | cf81d55 | 2005-03-31 04:52:26 +0000 | [diff] [blame] | 177 | VG_(tdict).tool_eq_Error = eq; |
| 178 | VG_(tdict).tool_pp_Error = pp; |
| 179 | VG_(tdict).tool_update_extra = update; |
| 180 | VG_(tdict).tool_recognised_suppression = recog; |
| 181 | VG_(tdict).tool_read_extra_suppression_info = read_extra; |
| 182 | VG_(tdict).tool_error_matches_suppression = matches; |
| 183 | VG_(tdict).tool_get_error_name = name; |
| 184 | VG_(tdict).tool_print_extra_suppression_info = print_extra; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 185 | } |
| 186 | |
| 187 | void VG_(needs_command_line_options)( |
| 188 | Bool (*process)(Char*), |
| 189 | void (*usage)(void), |
| 190 | void (*debug_usage)(void) |
| 191 | ) |
| 192 | { |
| 193 | VG_(needs).command_line_options = True; |
njn | cf81d55 | 2005-03-31 04:52:26 +0000 | [diff] [blame] | 194 | VG_(tdict).tool_process_cmd_line_option = process; |
| 195 | VG_(tdict).tool_print_usage = usage; |
| 196 | VG_(tdict).tool_print_debug_usage = debug_usage; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 197 | } |
| 198 | |
| 199 | void VG_(needs_client_requests)( |
| 200 | Bool (*handle)(ThreadId, UWord*, UWord*) |
| 201 | ) |
| 202 | { |
| 203 | VG_(needs).client_requests = True; |
njn | cf81d55 | 2005-03-31 04:52:26 +0000 | [diff] [blame] | 204 | VG_(tdict).tool_handle_client_request = handle; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | void VG_(needs_syscall_wrapper)( |
| 208 | void(*pre) (ThreadId, UInt), |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 209 | void(*post)(ThreadId, UInt, SysRes res) |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 210 | ) |
| 211 | { |
| 212 | VG_(needs).syscall_wrapper = True; |
njn | cf81d55 | 2005-03-31 04:52:26 +0000 | [diff] [blame] | 213 | VG_(tdict).tool_pre_syscall = pre; |
| 214 | VG_(tdict).tool_post_syscall = post; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | void VG_(needs_sanity_checks)( |
| 218 | Bool(*cheap)(void), |
| 219 | Bool(*expen)(void) |
| 220 | ) |
| 221 | { |
| 222 | VG_(needs).sanity_checks = True; |
njn | cf81d55 | 2005-03-31 04:52:26 +0000 | [diff] [blame] | 223 | VG_(tdict).tool_cheap_sanity_check = cheap; |
| 224 | VG_(tdict).tool_expensive_sanity_check = expen; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 225 | } |
| 226 | |
njn | fc51f8d | 2005-06-21 03:20:17 +0000 | [diff] [blame] | 227 | void VG_(needs_malloc_replacement)( |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 228 | void* (*malloc) ( ThreadId, SizeT ), |
| 229 | void* (*__builtin_new) ( ThreadId, SizeT ), |
| 230 | void* (*__builtin_vec_new) ( ThreadId, SizeT ), |
| 231 | void* (*memalign) ( ThreadId, SizeT, SizeT ), |
| 232 | void* (*calloc) ( ThreadId, SizeT, SizeT ), |
| 233 | void (*free) ( ThreadId, void* ), |
| 234 | void (*__builtin_delete) ( ThreadId, void* ), |
| 235 | void (*__builtin_vec_delete) ( ThreadId, void* ), |
| 236 | void* (*realloc) ( ThreadId, void*, SizeT ), |
| 237 | SizeT client_malloc_redzone_szB |
| 238 | ) |
| 239 | { |
njn | fc51f8d | 2005-06-21 03:20:17 +0000 | [diff] [blame] | 240 | VG_(needs).malloc_replacement = True; |
| 241 | VG_(tdict).tool_malloc = malloc; |
| 242 | VG_(tdict).tool___builtin_new = __builtin_new; |
| 243 | VG_(tdict).tool___builtin_vec_new = __builtin_vec_new; |
| 244 | VG_(tdict).tool_memalign = memalign; |
| 245 | VG_(tdict).tool_calloc = calloc; |
| 246 | VG_(tdict).tool_free = free; |
| 247 | VG_(tdict).tool___builtin_delete = __builtin_delete; |
| 248 | VG_(tdict).tool___builtin_vec_delete = __builtin_vec_delete; |
| 249 | VG_(tdict).tool_realloc = realloc; |
| 250 | VG_(tdict).tool_client_redzone_szB = client_malloc_redzone_szB; |
njn | 8a97c6d | 2005-03-31 04:37:24 +0000 | [diff] [blame] | 251 | } |
| 252 | |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 253 | |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 254 | /*--------------------------------------------------------------------*/ |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 255 | /* Tracked events */ |
| 256 | |
| 257 | #define DEF(fn, args...) \ |
| 258 | void VG_(fn)(void(*f)(args)) \ |
| 259 | { \ |
| 260 | VG_(tdict).fn = f; \ |
| 261 | } |
| 262 | |
| 263 | #define DEF2(fn, args...) \ |
njn | af839f5 | 2005-06-23 03:27:57 +0000 | [diff] [blame] | 264 | void VG_(fn)(VG_REGPARM(1) void(*f)(args)) \ |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 265 | { \ |
| 266 | VG_(tdict).fn = f; \ |
| 267 | } |
| 268 | |
| 269 | DEF(track_new_mem_startup, Addr, SizeT, Bool, Bool, Bool) |
| 270 | DEF(track_new_mem_stack_signal, Addr, SizeT) |
| 271 | DEF(track_new_mem_brk, Addr, SizeT) |
| 272 | DEF(track_new_mem_mmap, Addr, SizeT, Bool, Bool, Bool) |
| 273 | |
| 274 | DEF(track_copy_mem_remap, Addr, Addr, SizeT) |
| 275 | DEF(track_change_mem_mprotect, Addr, SizeT, Bool, Bool, Bool) |
| 276 | DEF(track_die_mem_stack_signal, Addr, SizeT) |
| 277 | DEF(track_die_mem_brk, Addr, SizeT) |
| 278 | DEF(track_die_mem_munmap, Addr, SizeT) |
| 279 | |
| 280 | DEF2(track_new_mem_stack_4, Addr) |
| 281 | DEF2(track_new_mem_stack_8, Addr) |
| 282 | DEF2(track_new_mem_stack_12, Addr) |
| 283 | DEF2(track_new_mem_stack_16, Addr) |
| 284 | DEF2(track_new_mem_stack_32, Addr) |
| 285 | DEF (track_new_mem_stack, Addr, SizeT) |
| 286 | |
| 287 | DEF2(track_die_mem_stack_4, Addr) |
| 288 | DEF2(track_die_mem_stack_8, Addr) |
| 289 | DEF2(track_die_mem_stack_12, Addr) |
| 290 | DEF2(track_die_mem_stack_16, Addr) |
| 291 | DEF2(track_die_mem_stack_32, Addr) |
| 292 | DEF (track_die_mem_stack, Addr, SizeT) |
| 293 | |
| 294 | DEF(track_ban_mem_stack, Addr, SizeT) |
| 295 | |
| 296 | DEF(track_pre_mem_read, CorePart, ThreadId, Char*, Addr, SizeT) |
| 297 | DEF(track_pre_mem_read_asciiz, CorePart, ThreadId, Char*, Addr) |
| 298 | DEF(track_pre_mem_write, CorePart, ThreadId, Char*, Addr, SizeT) |
| 299 | DEF(track_post_mem_write, CorePart, ThreadId, Addr, SizeT) |
| 300 | |
| 301 | DEF(track_pre_reg_read, CorePart, ThreadId, Char*, OffT, SizeT) |
| 302 | DEF(track_post_reg_write, CorePart, ThreadId, OffT, SizeT) |
| 303 | |
| 304 | DEF(track_post_reg_write_clientcall_return, ThreadId, OffT, SizeT, Addr) |
| 305 | |
| 306 | DEF(track_thread_run, ThreadId) |
| 307 | |
| 308 | DEF(track_post_thread_create, ThreadId, ThreadId) |
| 309 | DEF(track_post_thread_join, ThreadId, ThreadId) |
| 310 | |
| 311 | DEF(track_pre_mutex_lock, ThreadId, void*) |
| 312 | DEF(track_post_mutex_lock, ThreadId, void*) |
| 313 | DEF(track_post_mutex_unlock, ThreadId, void*) |
| 314 | |
| 315 | DEF(track_pre_deliver_signal, ThreadId, Int sigNo, Bool) |
| 316 | DEF(track_post_deliver_signal, ThreadId, Int sigNo) |
| 317 | |
njn | 51d827b | 2005-05-09 01:02:08 +0000 | [diff] [blame] | 318 | /*--------------------------------------------------------------------*/ |
| 319 | /*--- end ---*/ |
njn | 810086f | 2002-11-14 12:42:47 +0000 | [diff] [blame] | 320 | /*--------------------------------------------------------------------*/ |