njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
| 3 | /*--- The core/tool interface. pub_tool_tooliface.h ---*/ |
| 4 | /*--------------------------------------------------------------------*/ |
| 5 | |
| 6 | /* |
| 7 | This file is part of Valgrind, a dynamic binary instrumentation |
| 8 | framework. |
| 9 | |
| 10 | Copyright (C) 2000-2005 Julian Seward |
| 11 | jseward@acm.org |
| 12 | |
| 13 | This program is free software; you can redistribute it and/or |
| 14 | modify it under the terms of the GNU General Public License as |
| 15 | published by the Free Software Foundation; either version 2 of the |
| 16 | License, or (at your option) any later version. |
| 17 | |
| 18 | This program is distributed in the hope that it will be useful, but |
| 19 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 21 | General Public License for more details. |
| 22 | |
| 23 | You should have received a copy of the GNU General Public License |
| 24 | along with this program; if not, write to the Free Software |
| 25 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 26 | 02111-1307, USA. |
| 27 | |
| 28 | The GNU General Public License is contained in the file COPYING. |
| 29 | */ |
| 30 | |
| 31 | #ifndef __PUB_TOOL_TOOLIFACE_H |
| 32 | #define __PUB_TOOL_TOOLIFACE_H |
| 33 | |
njn | acd885a | 2005-05-16 20:40:51 +0000 | [diff] [blame] | 34 | #include "pub_tool_errormgr.h" // for Error, Supp |
| 35 | #include "libvex.h" // for VexGuestLayout |
| 36 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 37 | /* ------------------------------------------------------------------ */ |
| 38 | /* The interface version */ |
| 39 | |
| 40 | /* The version number indicates binary-incompatible changes to the |
| 41 | interface; if the core and tool versions don't match, Valgrind |
| 42 | will abort. */ |
| 43 | #define VG_CORE_INTERFACE_VERSION 8 |
| 44 | |
| 45 | typedef struct _ToolInfo { |
| 46 | Int sizeof_ToolInfo; |
| 47 | Int interface_version; |
| 48 | |
| 49 | /* Initialise tool. Must do the following: |
| 50 | - initialise the `details' struct, via the VG_(details_*)() functions |
| 51 | - register any helpers called by generated code |
| 52 | |
| 53 | May do the following: |
| 54 | - initialise the `needs' struct to indicate certain requirements, via |
| 55 | the VG_(needs_*)() functions |
| 56 | - initialize all the tool's entrypoints via the VG_(init_*)() functions |
| 57 | - register any tool-specific profiling events |
| 58 | - any other tool-specific initialisation |
| 59 | */ |
| 60 | void (*tl_pre_clo_init) ( void ); |
| 61 | |
| 62 | /* Specifies how big the shadow segment should be as a ratio to the |
| 63 | client address space. 0 for no shadow segment. */ |
| 64 | float shadow_ratio; |
| 65 | } ToolInfo; |
| 66 | |
| 67 | /* Every tool must include this macro somewhere, exactly once. */ |
| 68 | #define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init, shadow) \ |
| 69 | const ToolInfo VG_(tool_info) = { \ |
| 70 | .sizeof_ToolInfo = sizeof(ToolInfo), \ |
| 71 | .interface_version = VG_CORE_INTERFACE_VERSION, \ |
| 72 | .tl_pre_clo_init = pre_clo_init, \ |
| 73 | .shadow_ratio = shadow, \ |
| 74 | }; |
| 75 | |
| 76 | /* ------------------------------------------------------------------ */ |
| 77 | /* Basic tool functions */ |
| 78 | |
| 79 | extern void VG_(basic_tool_funcs)( |
| 80 | // Do any initialisation that can only be done after command line |
| 81 | // processing. |
| 82 | void (*post_clo_init)(void), |
| 83 | |
| 84 | // Instrument a basic block. Must be a true function, ie. the same input |
| 85 | // always results in the same output, because basic blocks can be |
| 86 | // retranslated. Unless you're doing something really strange... |
| 87 | IRBB* (*instrument)(IRBB* bb_in, VexGuestLayout* layout, |
| 88 | IRType gWordTy, IRType hWordTy ), |
| 89 | |
| 90 | // Finish up, print out any results, etc. `exitcode' is program's exit |
| 91 | // code. The shadow can be found with VG_(get_exit_status_shadow)(). |
| 92 | void (*fini)(Int) |
| 93 | ); |
| 94 | |
| 95 | /* ------------------------------------------------------------------ */ |
| 96 | /* Details */ |
| 97 | |
| 98 | /* Default value for avg_translations_sizeB (in bytes), indicating typical |
| 99 | code expansion of about 6:1. */ |
| 100 | #define VG_DEFAULT_TRANS_SIZEB 100 |
| 101 | |
| 102 | /* Information used in the startup message. `name' also determines the |
| 103 | string used for identifying suppressions in a suppression file as |
| 104 | belonging to this tool. `version' can be NULL, in which case (not |
| 105 | surprisingly) no version info is printed; this mechanism is designed for |
| 106 | tools distributed with Valgrind that share a version number with |
| 107 | Valgrind. Other tools not distributed as part of Valgrind should |
| 108 | probably have their own version number. */ |
| 109 | extern void VG_(details_name) ( Char* name ); |
| 110 | extern void VG_(details_version) ( Char* version ); |
| 111 | extern void VG_(details_description) ( Char* description ); |
| 112 | extern void VG_(details_copyright_author) ( Char* copyright_author ); |
| 113 | |
| 114 | /* Average size of a translation, in bytes, so that the translation |
| 115 | storage machinery can allocate memory appropriately. Not critical, |
| 116 | setting is optional. */ |
| 117 | extern void VG_(details_avg_translation_sizeB) ( UInt size ); |
| 118 | |
| 119 | /* String printed if an `tl_assert' assertion fails or VG_(tool_panic) |
| 120 | is called. Should probably be an email address. */ |
| 121 | extern void VG_(details_bug_reports_to) ( Char* bug_reports_to ); |
| 122 | |
| 123 | /* ------------------------------------------------------------------ */ |
| 124 | /* Needs */ |
| 125 | |
| 126 | /* Booleans that decide core behaviour, but don't require extra |
| 127 | operations to be defined if `True' */ |
| 128 | |
| 129 | /* Should __libc_freeres() be run? Bugs in it can crash the tool. */ |
| 130 | extern void VG_(needs_libc_freeres) ( void ); |
| 131 | |
| 132 | /* Want to have errors detected by Valgrind's core reported? Includes: |
| 133 | - pthread API errors (many; eg. unlocking a non-locked mutex) |
| 134 | - invalid file descriptors to blocking syscalls read() and write() |
| 135 | - bad signal numbers passed to sigaction() |
| 136 | - attempt to install signal handler for SIGKILL or SIGSTOP */ |
| 137 | extern void VG_(needs_core_errors) ( void ); |
| 138 | |
| 139 | /* Booleans that indicate extra operations are defined; if these are True, |
| 140 | the corresponding template functions (given below) must be defined. A |
| 141 | lot like being a member of a type class. */ |
| 142 | |
| 143 | /* Want to report errors from tool? This implies use of suppressions, too. */ |
| 144 | extern void VG_(needs_tool_errors) ( |
| 145 | // Identify if two errors are equal, or equal enough. `res' indicates how |
| 146 | // close is "close enough". `res' should be passed on as necessary, eg. if |
| 147 | // the Error's `extra' part contains an ExeContext, `res' should be |
| 148 | // passed to VG_(eq_ExeContext)() if the ExeContexts are considered. Other |
| 149 | // than that, probably don't worry about it unless you have lots of very |
| 150 | // similar errors occurring. |
| 151 | Bool (*eq_Error)(VgRes res, Error* e1, Error* e2), |
| 152 | |
| 153 | // Print error context. |
| 154 | void (*pp_Error)(Error* err), |
| 155 | |
| 156 | // Should fill in any details that could be postponed until after the |
| 157 | // decision whether to ignore the error (ie. details not affecting the |
| 158 | // result of VG_(tdict).tool_eq_Error()). This saves time when errors |
| 159 | // are ignored. |
| 160 | // Yuk. |
| 161 | // Return value: must be the size of the `extra' part in bytes -- used by |
| 162 | // the core to make a copy. |
| 163 | UInt (*update_extra)(Error* err), |
| 164 | |
| 165 | // Return value indicates recognition. If recognised, must set skind using |
| 166 | // VG_(set_supp_kind)(). |
| 167 | Bool (*recognised_suppression)(Char* name, Supp* su), |
| 168 | |
| 169 | // Read any extra info for this suppression kind. Most likely for filling |
| 170 | // in the `extra' and `string' parts (with VG_(set_supp_{extra, string})()) |
| 171 | // of a suppression if necessary. Should return False if a syntax error |
| 172 | // occurred, True otherwise. |
| 173 | Bool (*read_extra_suppression_info)(Int fd, Char* buf, Int nBuf, Supp* su), |
| 174 | |
| 175 | // This should just check the kinds match and maybe some stuff in the |
| 176 | // `string' and `extra' field if appropriate (using VG_(get_supp_*)() to |
| 177 | // get the relevant suppression parts). |
| 178 | Bool (*error_matches_suppression)(Error* err, Supp* su), |
| 179 | |
| 180 | // This should return the suppression name, for --gen-suppressions, or NULL |
| 181 | // if that error type cannot be suppressed. This is the inverse of |
| 182 | // VG_(tdict).tool_recognised_suppression(). |
| 183 | Char* (*get_error_name)(Error* err), |
| 184 | |
| 185 | // This should print any extra info for the error, for --gen-suppressions, |
| 186 | // including the newline. This is the inverse of |
| 187 | // VG_(tdict).tool_read_extra_suppression_info(). |
| 188 | void (*print_extra_suppression_info)(Error* err) |
| 189 | ); |
| 190 | |
| 191 | |
| 192 | /* Is information kept about specific individual basic blocks? (Eg. for |
| 193 | cachegrind there are cost-centres for every instruction, stored at a |
| 194 | basic block level.) If so, it sometimes has to be discarded, because |
| 195 | .so mmap/munmap-ping or self-modifying code (informed by the |
| 196 | DISCARD_TRANSLATIONS user request) can cause one instruction address |
| 197 | to be used for more than one instruction in one program run... */ |
| 198 | extern void VG_(needs_basic_block_discards) ( |
| 199 | // Should discard any information that pertains to specific basic blocks |
| 200 | // or instructions within the address range given. |
| 201 | void (*discard_basic_block_info)(Addr a, SizeT size) |
| 202 | ); |
| 203 | |
| 204 | /* Tool defines its own command line options? */ |
| 205 | extern void VG_(needs_command_line_options) ( |
| 206 | // Return True if option was recognised. Presumably sets some state to |
| 207 | // record the option as well. |
| 208 | Bool (*process_cmd_line_option)(Char* argv), |
| 209 | |
| 210 | // Print out command line usage for options for normal tool operation. |
| 211 | void (*print_usage)(void), |
| 212 | |
| 213 | // Print out command line usage for options for debugging the tool. |
| 214 | void (*print_debug_usage)(void) |
| 215 | ); |
| 216 | |
| 217 | /* Tool defines its own client requests? */ |
| 218 | extern void VG_(needs_client_requests) ( |
| 219 | // If using client requests, the number of the first request should be equal |
| 220 | // to VG_USERREQ_TOOL_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two |
| 221 | // character identification for the string. The second and subsequent |
| 222 | // requests should follow. |
| 223 | // |
| 224 | // This function should use the VG_IS_TOOL_USERREQ macro (in |
| 225 | // include/valgrind.h) to first check if it's a request for this tool. Then |
| 226 | // should handle it if it's recognised (and return True), or return False if |
| 227 | // not recognised. arg_block[0] holds the request number, any further args |
| 228 | // from the request are in arg_block[1..]. 'ret' is for the return value... |
| 229 | // it should probably be filled, if only with 0. |
| 230 | Bool (*handle_client_request)(ThreadId tid, UWord* arg_block, UWord* ret) |
| 231 | ); |
| 232 | |
| 233 | /* Tool does stuff before and/or after system calls? */ |
| 234 | // Nb: If either of the pre_ functions malloc() something to return, the |
| 235 | // corresponding post_ function had better free() it! |
| 236 | extern void VG_(needs_syscall_wrapper) ( |
| 237 | void (* pre_syscall)(ThreadId tid, UInt syscallno), |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 238 | void (*post_syscall)(ThreadId tid, UInt syscallno, SysRes res) |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 239 | ); |
| 240 | |
| 241 | /* Are tool-state sanity checks performed? */ |
| 242 | // Can be useful for ensuring a tool's correctness. cheap_sanity_check() |
| 243 | // is called very frequently; expensive_sanity_check() is called less |
| 244 | // frequently and can be more involved. |
| 245 | extern void VG_(needs_sanity_checks) ( |
| 246 | Bool(*cheap_sanity_check)(void), |
| 247 | Bool(*expensive_sanity_check)(void) |
| 248 | ); |
| 249 | |
| 250 | /* Do we need to see data symbols? */ |
| 251 | extern void VG_(needs_data_syms) ( void ); |
| 252 | |
| 253 | /* Does the tool need shadow memory allocated? */ |
| 254 | extern void VG_(needs_shadow_memory)( void ); |
| 255 | |
njn | fc51f8d | 2005-06-21 03:20:17 +0000 | [diff] [blame^] | 256 | /* Does the tool replace malloc() and friends with its own versions? */ |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 257 | // The 'p' prefix avoids GCC complaints about overshadowing global names. |
njn | fc51f8d | 2005-06-21 03:20:17 +0000 | [diff] [blame^] | 258 | extern void VG_(needs_malloc_replacement)( |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 259 | void* (*pmalloc) ( ThreadId tid, SizeT n ), |
| 260 | void* (*p__builtin_new) ( ThreadId tid, SizeT n ), |
| 261 | void* (*p__builtin_vec_new) ( ThreadId tid, SizeT n ), |
| 262 | void* (*pmemalign) ( ThreadId tid, SizeT align, SizeT n ), |
| 263 | void* (*pcalloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ), |
| 264 | void (*pfree) ( ThreadId tid, void* p ), |
| 265 | void (*p__builtin_delete) ( ThreadId tid, void* p ), |
| 266 | void (*p__builtin_vec_delete) ( ThreadId tid, void* p ), |
| 267 | void* (*prealloc) ( ThreadId tid, void* p, SizeT new_size ), |
| 268 | SizeT client_malloc_redzone_szB |
| 269 | ); |
| 270 | |
| 271 | /* ------------------------------------------------------------------ */ |
| 272 | /* Core events to track */ |
| 273 | |
| 274 | /* Part of the core from which this call was made. Useful for determining |
| 275 | what kind of error message should be emitted. */ |
| 276 | typedef |
| 277 | enum { Vg_CoreStartup, Vg_CorePThread, Vg_CoreSignal, Vg_CoreSysCall, |
| 278 | Vg_CoreTranslate, Vg_CoreClientReq } |
| 279 | CorePart; |
| 280 | |
| 281 | /* Events happening in core to track. To be notified, pass a callback |
| 282 | function to the appropriate function. To ignore an event, don't do |
| 283 | anything (the default is for events to be ignored). |
| 284 | |
| 285 | Note that most events aren't passed a ThreadId. If the event is one called |
| 286 | from generated code (eg. new_mem_stack_*), you can use |
| 287 | VG_(get_running_tid)() to find it. Otherwise, it has to be passed in, |
| 288 | as in pre_mem_read, and so the event signature will require changing. |
| 289 | |
| 290 | Memory events (Nb: to track heap allocation/freeing, a tool must replace |
| 291 | malloc() et al. See above how to do this.) |
| 292 | |
| 293 | These ones occur at startup, upon some signals, and upon some syscalls |
| 294 | */ |
| 295 | void VG_(track_new_mem_startup) (void(*f)(Addr a, SizeT len, |
| 296 | Bool rr, Bool ww, Bool xx)); |
| 297 | void VG_(track_new_mem_stack_signal)(void(*f)(Addr a, SizeT len)); |
| 298 | void VG_(track_new_mem_brk) (void(*f)(Addr a, SizeT len)); |
| 299 | void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len, |
| 300 | Bool rr, Bool ww, Bool xx)); |
| 301 | |
| 302 | void VG_(track_copy_mem_remap) (void(*f)(Addr from, Addr to, SizeT len)); |
| 303 | void VG_(track_change_mem_mprotect) (void(*f)(Addr a, SizeT len, |
| 304 | Bool rr, Bool ww, Bool xx)); |
| 305 | void VG_(track_die_mem_stack_signal)(void(*f)(Addr a, SizeT len)); |
| 306 | void VG_(track_die_mem_brk) (void(*f)(Addr a, SizeT len)); |
| 307 | void VG_(track_die_mem_munmap) (void(*f)(Addr a, SizeT len)); |
| 308 | |
| 309 | /* These ones are called when SP changes. A tool could track these itself |
| 310 | (except for ban_mem_stack) but it's much easier to use the core's help. |
| 311 | |
| 312 | The specialised ones are called in preference to the general one, if they |
| 313 | are defined. These functions are called a lot if they are used, so |
| 314 | specialising can optimise things significantly. If any of the |
| 315 | specialised cases are defined, the general case must be defined too. |
| 316 | |
| 317 | Nb: all the specialised ones must use the VGA_REGPARM(n) attribute. |
| 318 | */ |
| 319 | void VG_(track_new_mem_stack_4) (VGA_REGPARM(1) void(*f)(Addr new_ESP)); |
| 320 | void VG_(track_new_mem_stack_8) (VGA_REGPARM(1) void(*f)(Addr new_ESP)); |
| 321 | void VG_(track_new_mem_stack_12)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); |
| 322 | void VG_(track_new_mem_stack_16)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); |
| 323 | void VG_(track_new_mem_stack_32)(VGA_REGPARM(1) void(*f)(Addr new_ESP)); |
| 324 | void VG_(track_new_mem_stack) (void(*f)(Addr a, SizeT len)); |
| 325 | |
| 326 | void VG_(track_die_mem_stack_4) (VGA_REGPARM(1) void(*f)(Addr die_ESP)); |
| 327 | void VG_(track_die_mem_stack_8) (VGA_REGPARM(1) void(*f)(Addr die_ESP)); |
| 328 | void VG_(track_die_mem_stack_12)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); |
| 329 | void VG_(track_die_mem_stack_16)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); |
| 330 | void VG_(track_die_mem_stack_32)(VGA_REGPARM(1) void(*f)(Addr die_ESP)); |
| 331 | void VG_(track_die_mem_stack) (void(*f)(Addr a, SizeT len)); |
| 332 | |
| 333 | /* Used for redzone at end of thread stacks */ |
| 334 | void VG_(track_ban_mem_stack) (void(*f)(Addr a, SizeT len)); |
| 335 | |
| 336 | /* These ones occur around syscalls, signal handling, etc */ |
| 337 | void VG_(track_pre_mem_read) (void(*f)(CorePart part, ThreadId tid, |
| 338 | Char* s, Addr a, SizeT size)); |
| 339 | void VG_(track_pre_mem_read_asciiz)(void(*f)(CorePart part, ThreadId tid, |
| 340 | Char* s, Addr a)); |
| 341 | void VG_(track_pre_mem_write) (void(*f)(CorePart part, ThreadId tid, |
| 342 | Char* s, Addr a, SizeT size)); |
| 343 | void VG_(track_post_mem_write) (void(*f)(CorePart part, ThreadId tid, |
| 344 | Addr a, SizeT size)); |
| 345 | |
| 346 | /* Register events. Use VG_(set_shadow_state_area)() to set the shadow regs |
| 347 | for these events. */ |
| 348 | void VG_(track_pre_reg_read) (void(*f)(CorePart part, ThreadId tid, |
| 349 | Char* s, OffT guest_state_offset, |
| 350 | SizeT size)); |
| 351 | void VG_(track_post_reg_write)(void(*f)(CorePart part, ThreadId tid, |
| 352 | OffT guest_state_offset, |
| 353 | SizeT size)); |
| 354 | |
| 355 | /* This one is called for malloc() et al if they are replaced by a tool. */ |
| 356 | void VG_(track_post_reg_write_clientcall_return)( |
| 357 | void(*f)(ThreadId tid, OffT guest_state_offset, SizeT size, Addr f)); |
| 358 | |
| 359 | |
| 360 | /* Scheduler events (not exhaustive) */ |
| 361 | void VG_(track_thread_run)(void(*f)(ThreadId tid)); |
| 362 | |
| 363 | |
| 364 | /* Thread events (not exhaustive) |
| 365 | |
| 366 | Called during thread create, before the new thread has run any |
| 367 | instructions (or touched any memory). |
| 368 | */ |
| 369 | void VG_(track_post_thread_create)(void(*f)(ThreadId tid, ThreadId child)); |
| 370 | void VG_(track_post_thread_join) (void(*f)(ThreadId joiner, ThreadId joinee)); |
| 371 | |
| 372 | /* Mutex events (not exhaustive) |
| 373 | "void *mutex" is really a pthread_mutex * |
| 374 | |
| 375 | Called before a thread can block while waiting for a mutex (called |
| 376 | regardless of whether the thread will block or not). */ |
| 377 | void VG_(track_pre_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); |
| 378 | |
| 379 | /* Called once the thread actually holds the mutex (always paired with |
| 380 | pre_mutex_lock). */ |
| 381 | void VG_(track_post_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); |
| 382 | |
| 383 | /* Called after a thread has released a mutex (no need for a corresponding |
| 384 | pre_mutex_unlock, because unlocking can't block). */ |
| 385 | void VG_(track_post_mutex_unlock)(void(*f)(ThreadId tid, void* mutex)); |
| 386 | |
| 387 | /* Signal events (not exhaustive) |
| 388 | |
| 389 | ... pre_send_signal, post_send_signal ... |
| 390 | |
| 391 | Called before a signal is delivered; `alt_stack' indicates if it is |
| 392 | delivered on an alternative stack. */ |
| 393 | void VG_(track_pre_deliver_signal) (void(*f)(ThreadId tid, Int sigNo, |
| 394 | Bool alt_stack)); |
| 395 | /* Called after a signal is delivered. Nb: unfortunately, if the signal |
| 396 | handler longjmps, this won't be called. */ |
| 397 | void VG_(track_post_deliver_signal)(void(*f)(ThreadId tid, Int sigNo)); |
| 398 | |
| 399 | /* Others... condition variables... |
| 400 | ... |
| 401 | Shadow memory management |
| 402 | */ |
| 403 | void VG_(track_init_shadow_page)(void(*f)(Addr p)); |
| 404 | |
| 405 | #endif // __PUB_TOOL_TOOLIFACE_H |
| 406 | |
| 407 | /*--------------------------------------------------------------------*/ |
| 408 | /*--- end ---*/ |
| 409 | /*--------------------------------------------------------------------*/ |