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 | |
njn | 9f20746 | 2009-03-10 22:02:09 +0000 | [diff] [blame] | 10 | Copyright (C) 2000-2009 Julian Seward |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 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 |
njn | 0fc5cbd | 2006-10-18 21:50:26 +0000 | [diff] [blame] | 35 | #include "libvex.h" // for all Vex stuff |
njn | acd885a | 2005-05-16 20:40:51 +0000 | [diff] [blame] | 36 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 37 | /* ------------------------------------------------------------------ */ |
| 38 | /* The interface version */ |
| 39 | |
njn | 08ce7b3 | 2009-02-27 03:38:28 +0000 | [diff] [blame] | 40 | /* Initialise tool. Must do the following: |
| 41 | - initialise the `details' struct, via the VG_(details_*)() functions |
| 42 | - register the basic tool functions, via VG_(basic_tool_funcs)(). |
| 43 | May do the following: |
| 44 | - initialise the `needs' struct to indicate certain requirements, via |
| 45 | the VG_(needs_*)() functions |
| 46 | - any other tool-specific initialisation |
| 47 | */ |
| 48 | extern void (*VG_(tl_pre_clo_init)) ( void ); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 49 | |
njn | 08ce7b3 | 2009-02-27 03:38:28 +0000 | [diff] [blame] | 50 | /* Every tool must include this macro somewhere, exactly once. The |
| 51 | interface version is no longer relevant, but we kept the same name |
| 52 | to avoid requiring changes to tools. |
| 53 | */ |
| 54 | #define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init) \ |
| 55 | void (*VG_(tl_pre_clo_init)) ( void ) = pre_clo_init; |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 56 | |
| 57 | /* ------------------------------------------------------------------ */ |
| 58 | /* Basic tool functions */ |
| 59 | |
sewardj | 461df9c | 2006-01-17 02:06:39 +0000 | [diff] [blame] | 60 | /* The tool_instrument function is passed as a callback to |
sewardj | 7ce6239 | 2006-10-15 12:48:18 +0000 | [diff] [blame] | 61 | LibVEX_Translate. VgCallbackClosure carries additional info |
sewardj | 461df9c | 2006-01-17 02:06:39 +0000 | [diff] [blame] | 62 | which the instrumenter might like to know, but which is opaque to |
| 63 | Vex. |
| 64 | */ |
| 65 | typedef |
| 66 | struct { |
| 67 | Addr64 nraddr; /* non-redirected guest address */ |
| 68 | Addr64 readdr; /* redirected guest address */ |
| 69 | ThreadId tid; /* tid requesting translation */ |
| 70 | } |
| 71 | VgCallbackClosure; |
| 72 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 73 | extern void VG_(basic_tool_funcs)( |
| 74 | // Do any initialisation that can only be done after command line |
| 75 | // processing. |
| 76 | void (*post_clo_init)(void), |
| 77 | |
sewardj | 4ba057c | 2005-10-18 12:04:18 +0000 | [diff] [blame] | 78 | // Instrument a basic block. Must be a true function, ie. the same |
| 79 | // input always results in the same output, because basic blocks |
sewardj | 7ce6239 | 2006-10-15 12:48:18 +0000 | [diff] [blame] | 80 | // can be retranslated, unless you're doing something really |
| 81 | // strange. Anyway, the arguments. Mostly they are straightforward |
| 82 | // except for the distinction between redirected and non-redirected |
| 83 | // guest code addresses, which is important to understand. |
| 84 | // |
| 85 | // VgCallBackClosure* closure contains extra arguments passed |
| 86 | // from Valgrind to the instrumenter, which Vex doesn't know about. |
| 87 | // You are free to look inside this structure. |
| 88 | // |
| 89 | // * closure->tid is the ThreadId of the thread requesting the |
| 90 | // translation. Not sure why this is here; perhaps callgrind |
| 91 | // uses it. |
| 92 | // |
| 93 | // * closure->nraddr is the non-redirected guest address of the |
| 94 | // start of the translation. In other words, the translation is |
| 95 | // being constructed because the guest program jumped to |
| 96 | // closure->nraddr but no translation of it was found. |
| 97 | // |
| 98 | // * closure->readdr is the redirected guest address, from which |
| 99 | // the translation was really made. |
| 100 | // |
| 101 | // To clarify this, consider what happens when, in Memcheck, the |
| 102 | // first call to malloc() happens. The guest program will be |
| 103 | // trying to jump to malloc() in libc; hence ->nraddr will contain |
| 104 | // that address. However, Memcheck intercepts and replaces |
| 105 | // malloc, hence ->readdr will be the address of Memcheck's |
| 106 | // malloc replacement in |
| 107 | // coregrind/m_replacemalloc/vg_replacemalloc.c. It follows |
| 108 | // that the first IMark in the translation will be labelled as |
| 109 | // from ->readdr rather than ->nraddr. |
| 110 | // |
| 111 | // Since most functions are not redirected, the majority of the |
| 112 | // time ->nraddr will be the same as ->readdr. However, you |
| 113 | // cannot assume this: if your tool has metadata associated |
| 114 | // with code addresses it will get into deep trouble if it does |
| 115 | // make this assumption. |
| 116 | // |
sewardj | 0b9d74a | 2006-12-24 02:24:11 +0000 | [diff] [blame] | 117 | // IRSB* sb_in is the incoming superblock to be instrumented, |
| 118 | // in flat IR form. |
sewardj | 7ce6239 | 2006-10-15 12:48:18 +0000 | [diff] [blame] | 119 | // |
| 120 | // VexGuestLayout* layout contains limited info on the layout of |
| 121 | // the guest state: where the stack pointer and program counter |
| 122 | // are, and which fields should be regarded as 'always defined'. |
| 123 | // Memcheck uses this. |
| 124 | // |
| 125 | // VexGuestExtents* vge points to a structure which states the |
| 126 | // precise byte ranges of original code from which this translation |
| 127 | // was made (there may be up to three different ranges involved). |
| 128 | // Note again that these are the real addresses from which the code |
| 129 | // came. And so it should be the case that closure->readdr is the |
| 130 | // same as vge->base[0]; indeed Cachegrind contains this assertion. |
| 131 | // |
| 132 | // Tools which associate shadow data with code addresses |
| 133 | // (cachegrind, callgrind) need to be particularly clear about |
| 134 | // whether they are making the association with redirected or |
| 135 | // non-redirected code addresses. Both approaches are viable |
| 136 | // but you do need to understand what's going on. See comments |
| 137 | // below on discard_basic_block_info(). |
| 138 | // |
| 139 | // IRType gWordTy and IRType hWordTy contain the types of native |
| 140 | // words on the guest (simulated) and host (real) CPUs. They will |
| 141 | // by either Ity_I32 or Ity_I64. So far we have never built a |
| 142 | // cross-architecture Valgrind so they should always be the same. |
| 143 | // |
sewardj | c87b5ec | 2006-10-15 13:46:18 +0000 | [diff] [blame] | 144 | /* --- Further comments about the IR that your --- */ |
| 145 | /* --- instrumentation function will receive. --- */ |
| 146 | /* |
njn | a3cc29f | 2007-02-05 23:23:55 +0000 | [diff] [blame] | 147 | In the incoming IRSB, the IR for each instruction begins with an |
sewardj | c87b5ec | 2006-10-15 13:46:18 +0000 | [diff] [blame] | 148 | IRStmt_IMark, which states the address and length of the |
| 149 | instruction from which this IR came. This makes it easy for |
| 150 | profiling-style tools to know precisely which guest code |
| 151 | addresses are being executed. |
| 152 | |
| 153 | However, before the first IRStmt_IMark, there may be other IR |
| 154 | statements -- a preamble. In most cases this preamble is empty, |
| 155 | but when it isn't, what it contains is some supporting IR that |
| 156 | the JIT uses to ensure control flow works correctly. This |
| 157 | preamble does not modify any architecturally defined guest state |
| 158 | (registers or memory) and so does not contain anything that will |
| 159 | be of interest to your tool. |
| 160 | |
| 161 | You should therefore |
| 162 | |
| 163 | (1) copy any IR preceding the first IMark verbatim to the start |
njn | a3cc29f | 2007-02-05 23:23:55 +0000 | [diff] [blame] | 164 | of the output IRSB. |
sewardj | c87b5ec | 2006-10-15 13:46:18 +0000 | [diff] [blame] | 165 | |
| 166 | (2) not try to instrument it or modify it in any way. |
| 167 | |
| 168 | For the record, stuff that may be in the preamble at |
| 169 | present is: |
| 170 | |
| 171 | - A self-modifying-code check has been requested for this block. |
| 172 | The preamble will contain instructions to checksum the block, |
| 173 | compare against the expected value, and exit the dispatcher |
| 174 | requesting a discard (hence forcing a retranslation) if they |
| 175 | don't match. |
| 176 | |
| 177 | - This block is known to be the entry point of a wrapper of some |
sewardj | 358ebea | 2006-10-15 13:47:43 +0000 | [diff] [blame] | 178 | function F. In this case the preamble contains code to write |
sewardj | c87b5ec | 2006-10-15 13:46:18 +0000 | [diff] [blame] | 179 | the address of the original F (the fn being wrapped) into a |
| 180 | 'hidden' guest state register _NRADDR. The wrapper can later |
| 181 | read this register using a client request and make a |
| 182 | non-redirected call to it using another client-request-like |
| 183 | magic macro. |
| 184 | |
| 185 | - For platforms that use the AIX ABI (including ppc64-linux), it |
sewardj | 358ebea | 2006-10-15 13:47:43 +0000 | [diff] [blame] | 186 | is necessary to have a preamble even for replacement functions |
| 187 | (not just for wrappers), because it is necessary to switch the |
| 188 | R2 register (constant-pool pointer) to a different value when |
| 189 | swizzling the program counter. |
sewardj | c87b5ec | 2006-10-15 13:46:18 +0000 | [diff] [blame] | 190 | |
| 191 | Hence the preamble pushes both R2 and LR (the return address) |
| 192 | on a small 16-entry stack in the guest state and sets R2 to an |
| 193 | appropriate value for the wrapper/replacement fn. LR is then |
| 194 | set so that the wrapper/replacement fn returns to a magic IR |
| 195 | stub which restores R2 and LR and returns. |
| 196 | |
| 197 | It's all hugely ugly and fragile. And it places a stringent |
| 198 | requirement on m_debuginfo to find out the correct R2 (toc |
| 199 | pointer) value for the wrapper/replacement function. So much |
| 200 | so that m_redir will refuse to honour a redirect-to-me request |
| 201 | if it cannot find (by asking m_debuginfo) a plausible R2 value |
| 202 | for 'me'. |
| 203 | |
| 204 | Because this mechanism maintains a shadow stack of (R2,LR) |
| 205 | pairs in the guest state, it will fail if the |
| 206 | wrapper/redirection function, or anything it calls, longjumps |
| 207 | out past the wrapper, because then the magic return stub will |
| 208 | not be run and so the shadow stack will not be popped. So it |
| 209 | will quickly fill up. Fortunately none of this applies to |
| 210 | {x86,amd64,ppc32}-linux; on those platforms, wrappers can |
| 211 | longjump and recurse arbitrarily and everything should work |
| 212 | fine. |
sewardj | f1962d3 | 2006-10-19 13:22:16 +0000 | [diff] [blame] | 213 | |
| 214 | Note that copying the preamble verbatim may cause complications |
| 215 | for your instrumenter if you shadow IR temporaries. See big |
| 216 | comment in MC_(instrument) in memcheck/mc_translate.c for |
| 217 | details. |
sewardj | c87b5ec | 2006-10-15 13:46:18 +0000 | [diff] [blame] | 218 | */ |
sewardj | 0b9d74a | 2006-12-24 02:24:11 +0000 | [diff] [blame] | 219 | IRSB*(*instrument)(VgCallbackClosure* closure, |
| 220 | IRSB* sb_in, |
sewardj | 7ce6239 | 2006-10-15 12:48:18 +0000 | [diff] [blame] | 221 | VexGuestLayout* layout, |
| 222 | VexGuestExtents* vge, |
| 223 | IRType gWordTy, |
| 224 | IRType hWordTy), |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 225 | |
| 226 | // Finish up, print out any results, etc. `exitcode' is program's exit |
| 227 | // code. The shadow can be found with VG_(get_exit_status_shadow)(). |
| 228 | void (*fini)(Int) |
| 229 | ); |
| 230 | |
| 231 | /* ------------------------------------------------------------------ */ |
| 232 | /* Details */ |
| 233 | |
| 234 | /* Default value for avg_translations_sizeB (in bytes), indicating typical |
| 235 | code expansion of about 6:1. */ |
sewardj | 9644cfd | 2006-10-17 02:25:50 +0000 | [diff] [blame] | 236 | #define VG_DEFAULT_TRANS_SIZEB 172 |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 237 | |
| 238 | /* Information used in the startup message. `name' also determines the |
| 239 | string used for identifying suppressions in a suppression file as |
| 240 | belonging to this tool. `version' can be NULL, in which case (not |
| 241 | surprisingly) no version info is printed; this mechanism is designed for |
| 242 | tools distributed with Valgrind that share a version number with |
| 243 | Valgrind. Other tools not distributed as part of Valgrind should |
| 244 | probably have their own version number. */ |
| 245 | extern void VG_(details_name) ( Char* name ); |
| 246 | extern void VG_(details_version) ( Char* version ); |
| 247 | extern void VG_(details_description) ( Char* description ); |
| 248 | extern void VG_(details_copyright_author) ( Char* copyright_author ); |
| 249 | |
| 250 | /* Average size of a translation, in bytes, so that the translation |
| 251 | storage machinery can allocate memory appropriately. Not critical, |
| 252 | setting is optional. */ |
| 253 | extern void VG_(details_avg_translation_sizeB) ( UInt size ); |
| 254 | |
| 255 | /* String printed if an `tl_assert' assertion fails or VG_(tool_panic) |
| 256 | is called. Should probably be an email address. */ |
| 257 | extern void VG_(details_bug_reports_to) ( Char* bug_reports_to ); |
| 258 | |
| 259 | /* ------------------------------------------------------------------ */ |
| 260 | /* Needs */ |
| 261 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 262 | /* Should __libc_freeres() be run? Bugs in it can crash the tool. */ |
| 263 | extern void VG_(needs_libc_freeres) ( void ); |
| 264 | |
| 265 | /* Want to have errors detected by Valgrind's core reported? Includes: |
njn | 0087c50 | 2005-07-01 04:15:36 +0000 | [diff] [blame] | 266 | - pthread API errors (many; eg. unlocking a non-locked mutex) |
| 267 | [currently disabled] |
| 268 | - invalid file descriptors to syscalls like read() and write() |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 269 | - bad signal numbers passed to sigaction() |
| 270 | - attempt to install signal handler for SIGKILL or SIGSTOP */ |
| 271 | extern void VG_(needs_core_errors) ( void ); |
| 272 | |
| 273 | /* Booleans that indicate extra operations are defined; if these are True, |
| 274 | the corresponding template functions (given below) must be defined. A |
| 275 | lot like being a member of a type class. */ |
| 276 | |
| 277 | /* Want to report errors from tool? This implies use of suppressions, too. */ |
| 278 | extern void VG_(needs_tool_errors) ( |
njn | a5453e9 | 2009-07-27 22:21:22 +0000 | [diff] [blame] | 279 | // Identify if two errors are equal, or close enough. This function is |
| 280 | // only called if e1 and e2 will have the same error kind. `res' indicates |
| 281 | // how close is "close enough". `res' should be passed on as necessary, |
| 282 | // eg. if the Error's `extra' part contains an ExeContext, `res' should be |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 283 | // passed to VG_(eq_ExeContext)() if the ExeContexts are considered. Other |
| 284 | // than that, probably don't worry about it unless you have lots of very |
| 285 | // similar errors occurring. |
| 286 | Bool (*eq_Error)(VgRes res, Error* e1, Error* e2), |
| 287 | |
sewardj | 5d9dc75 | 2009-07-15 14:52:18 +0000 | [diff] [blame] | 288 | // We give tools a chance to have a look at errors |
| 289 | // just before they are printed. That is, before_pp_Error is |
| 290 | // called just before pp_Error itself. This gives the tool a |
| 291 | // chance to look at the just-about-to-be-printed error, so as to |
| 292 | // emit any arbitrary output if wants to, before the error itself |
| 293 | // is printed. This functionality was added to allow Helgrind to |
| 294 | // print thread-announcement messages immediately before the |
| 295 | // errors that refer to them. |
| 296 | void (*before_pp_Error)(Error* err), |
| 297 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 298 | // Print error context. |
| 299 | void (*pp_Error)(Error* err), |
| 300 | |
sewardj | adb102f | 2007-11-09 23:21:44 +0000 | [diff] [blame] | 301 | // Should the core indicate which ThreadId each error comes from? |
| 302 | Bool show_ThreadIDs_for_errors, |
| 303 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 304 | // Should fill in any details that could be postponed until after the |
| 305 | // decision whether to ignore the error (ie. details not affecting the |
| 306 | // result of VG_(tdict).tool_eq_Error()). This saves time when errors |
| 307 | // are ignored. |
| 308 | // Yuk. |
| 309 | // Return value: must be the size of the `extra' part in bytes -- used by |
| 310 | // the core to make a copy. |
| 311 | UInt (*update_extra)(Error* err), |
| 312 | |
| 313 | // Return value indicates recognition. If recognised, must set skind using |
| 314 | // VG_(set_supp_kind)(). |
| 315 | Bool (*recognised_suppression)(Char* name, Supp* su), |
| 316 | |
| 317 | // Read any extra info for this suppression kind. Most likely for filling |
| 318 | // in the `extra' and `string' parts (with VG_(set_supp_{extra, string})()) |
| 319 | // of a suppression if necessary. Should return False if a syntax error |
njn | 35db56c | 2009-07-24 07:38:29 +0000 | [diff] [blame] | 320 | // occurred, True otherwise. bufpp and nBufp are the same as for |
| 321 | // VG_(get_line). |
| 322 | Bool (*read_extra_suppression_info)(Int fd, Char** bufpp, SizeT* nBufp, |
| 323 | Supp* su), |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 324 | |
| 325 | // This should just check the kinds match and maybe some stuff in the |
| 326 | // `string' and `extra' field if appropriate (using VG_(get_supp_*)() to |
| 327 | // get the relevant suppression parts). |
| 328 | Bool (*error_matches_suppression)(Error* err, Supp* su), |
| 329 | |
| 330 | // This should return the suppression name, for --gen-suppressions, or NULL |
| 331 | // if that error type cannot be suppressed. This is the inverse of |
| 332 | // VG_(tdict).tool_recognised_suppression(). |
| 333 | Char* (*get_error_name)(Error* err), |
| 334 | |
sewardj | 588adef | 2009-08-15 22:41:51 +0000 | [diff] [blame] | 335 | // This should print into buf[0..nBuf-1] any extra info for the |
| 336 | // error, for --gen-suppressions, but not including any leading |
| 337 | // spaces nor a trailing newline. When called, buf[0 .. nBuf-1] |
| 338 | // will be zero filled, and it is expected and checked that the |
| 339 | // last element is still zero after the call. In other words the |
| 340 | // tool may not overrun the buffer, and this is checked for. If |
| 341 | // there is any info printed in the buffer, return True, otherwise |
| 342 | // do nothing, and return False. This function is the inverse of |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 343 | // VG_(tdict).tool_read_extra_suppression_info(). |
sewardj | 588adef | 2009-08-15 22:41:51 +0000 | [diff] [blame] | 344 | Bool (*print_extra_suppression_info)(Error* err, |
| 345 | /*OUT*/Char* buf, Int nBuf) |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 346 | ); |
| 347 | |
sewardj | 5155dec | 2005-10-12 10:09:23 +0000 | [diff] [blame] | 348 | /* Is information kept by the tool about specific instructions or |
| 349 | translations? (Eg. for cachegrind there are cost-centres for every |
| 350 | instruction, stored in a per-translation fashion.) If so, the info |
| 351 | may have to be discarded when translations are unloaded (eg. due to |
| 352 | .so unloading, or otherwise at the discretion of m_transtab, eg |
| 353 | when the table becomes too full) to avoid stale information being |
| 354 | reused for new translations. */ |
sewardj | 0b9d74a | 2006-12-24 02:24:11 +0000 | [diff] [blame] | 355 | extern void VG_(needs_superblock_discards) ( |
sewardj | 5155dec | 2005-10-12 10:09:23 +0000 | [diff] [blame] | 356 | // Discard any information that pertains to specific translations |
sewardj | 4ba057c | 2005-10-18 12:04:18 +0000 | [diff] [blame] | 357 | // or instructions within the address range given. There are two |
| 358 | // possible approaches. |
| 359 | // - If info is being stored at a per-translation level, use orig_addr |
| 360 | // to identify which translation is being discarded. Each translation |
| 361 | // will be discarded exactly once. |
sewardj | 7ce6239 | 2006-10-15 12:48:18 +0000 | [diff] [blame] | 362 | // This orig_addr will match the closure->nraddr which was passed to |
| 363 | // to instrument() (see extensive comments above) when this |
| 364 | // translation was made. Note that orig_addr won't necessarily be |
| 365 | // the same as the first address in "extents". |
sewardj | 5155dec | 2005-10-12 10:09:23 +0000 | [diff] [blame] | 366 | // - If info is being stored at a per-instruction level, you can get |
| 367 | // the address range(s) being discarded by stepping through "extents". |
| 368 | // Note that any single instruction may belong to more than one |
| 369 | // translation, and so could be covered by the "extents" of more than |
| 370 | // one call to this function. |
| 371 | // Doing it the first way (as eg. Cachegrind does) is probably easier. |
sewardj | 0b9d74a | 2006-12-24 02:24:11 +0000 | [diff] [blame] | 372 | void (*discard_superblock_info)(Addr64 orig_addr, VexGuestExtents extents) |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 373 | ); |
| 374 | |
| 375 | /* Tool defines its own command line options? */ |
| 376 | extern void VG_(needs_command_line_options) ( |
| 377 | // Return True if option was recognised. Presumably sets some state to |
njn | a007859 | 2007-03-27 06:46:03 +0000 | [diff] [blame] | 378 | // record the option as well. Nb: tools can assume that the argv will |
| 379 | // never disappear. So they can, for example, store a pointer to a string |
| 380 | // within an option, rather than having to make a copy. |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 381 | Bool (*process_cmd_line_option)(Char* argv), |
| 382 | |
| 383 | // Print out command line usage for options for normal tool operation. |
| 384 | void (*print_usage)(void), |
| 385 | |
| 386 | // Print out command line usage for options for debugging the tool. |
| 387 | void (*print_debug_usage)(void) |
| 388 | ); |
| 389 | |
| 390 | /* Tool defines its own client requests? */ |
| 391 | extern void VG_(needs_client_requests) ( |
| 392 | // If using client requests, the number of the first request should be equal |
| 393 | // to VG_USERREQ_TOOL_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two |
| 394 | // character identification for the string. The second and subsequent |
| 395 | // requests should follow. |
| 396 | // |
| 397 | // This function should use the VG_IS_TOOL_USERREQ macro (in |
| 398 | // include/valgrind.h) to first check if it's a request for this tool. Then |
| 399 | // should handle it if it's recognised (and return True), or return False if |
| 400 | // not recognised. arg_block[0] holds the request number, any further args |
| 401 | // from the request are in arg_block[1..]. 'ret' is for the return value... |
| 402 | // it should probably be filled, if only with 0. |
| 403 | Bool (*handle_client_request)(ThreadId tid, UWord* arg_block, UWord* ret) |
| 404 | ); |
| 405 | |
| 406 | /* Tool does stuff before and/or after system calls? */ |
| 407 | // Nb: If either of the pre_ functions malloc() something to return, the |
| 408 | // corresponding post_ function had better free() it! |
sewardj | 1c0ce7a | 2009-07-01 08:10:49 +0000 | [diff] [blame] | 409 | // Also, the args are the 'original args' -- that is, it may be |
| 410 | // that the syscall pre-wrapper will modify the args before the |
| 411 | // syscall happens. So these args are the original, un-modified |
| 412 | // args. Finally, nArgs merely indicates the length of args[..], |
| 413 | // it does not indicate how many of those values are actually |
| 414 | // relevant to the syscall. args[0 .. nArgs-1] is guaranteed |
| 415 | // to be defined and to contain all the args for this syscall, |
| 416 | // possibly including some trailing zeroes. |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 417 | extern void VG_(needs_syscall_wrapper) ( |
sewardj | 1c0ce7a | 2009-07-01 08:10:49 +0000 | [diff] [blame] | 418 | void (* pre_syscall)(ThreadId tid, UInt syscallno, |
| 419 | UWord* args, UInt nArgs), |
| 420 | void (*post_syscall)(ThreadId tid, UInt syscallno, |
| 421 | UWord* args, UInt nArgs, SysRes res) |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 422 | ); |
| 423 | |
| 424 | /* Are tool-state sanity checks performed? */ |
| 425 | // Can be useful for ensuring a tool's correctness. cheap_sanity_check() |
| 426 | // is called very frequently; expensive_sanity_check() is called less |
| 427 | // frequently and can be more involved. |
| 428 | extern void VG_(needs_sanity_checks) ( |
| 429 | Bool(*cheap_sanity_check)(void), |
| 430 | Bool(*expensive_sanity_check)(void) |
| 431 | ); |
| 432 | |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 433 | /* Do we need to see variable type and location information? */ |
| 434 | extern void VG_(needs_var_info) ( void ); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 435 | |
njn | 09ca09b | 2005-10-16 17:48:09 +0000 | [diff] [blame] | 436 | /* Does the tool replace malloc() and friends with its own versions? |
| 437 | This has to be combined with the use of a vgpreload_<tool>.so module |
| 438 | or it won't work. See massif/Makefile.am for how to build it. */ |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 439 | // The 'p' prefix avoids GCC complaints about overshadowing global names. |
njn | fc51f8d | 2005-06-21 03:20:17 +0000 | [diff] [blame] | 440 | extern void VG_(needs_malloc_replacement)( |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 441 | void* (*pmalloc) ( ThreadId tid, SizeT n ), |
| 442 | void* (*p__builtin_new) ( ThreadId tid, SizeT n ), |
| 443 | void* (*p__builtin_vec_new) ( ThreadId tid, SizeT n ), |
| 444 | void* (*pmemalign) ( ThreadId tid, SizeT align, SizeT n ), |
| 445 | void* (*pcalloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ), |
| 446 | void (*pfree) ( ThreadId tid, void* p ), |
| 447 | void (*p__builtin_delete) ( ThreadId tid, void* p ), |
| 448 | void (*p__builtin_vec_delete) ( ThreadId tid, void* p ), |
| 449 | void* (*prealloc) ( ThreadId tid, void* p, SizeT new_size ), |
njn | 8b140de | 2009-02-17 04:31:18 +0000 | [diff] [blame] | 450 | SizeT (*pmalloc_usable_size) ( ThreadId tid, void* p), |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 451 | SizeT client_malloc_redzone_szB |
| 452 | ); |
| 453 | |
njn | ca54af3 | 2006-04-16 10:25:43 +0000 | [diff] [blame] | 454 | /* Can the tool do XML output? This is a slight misnomer, because the tool |
| 455 | * is not requesting the core to do anything, rather saying "I can handle |
| 456 | * it". */ |
sewardj | 5d9dc75 | 2009-07-15 14:52:18 +0000 | [diff] [blame] | 457 | extern void VG_(needs_xml_output) ( void ); |
njn | ca54af3 | 2006-04-16 10:25:43 +0000 | [diff] [blame] | 458 | |
sewardj | 81651dc | 2007-08-28 06:05:20 +0000 | [diff] [blame] | 459 | /* Does the tool want to have one final pass over the IR after tree |
| 460 | building but before instruction selection? If so specify the |
| 461 | function here. */ |
| 462 | extern void VG_(needs_final_IR_tidy_pass) ( IRSB*(*final_tidy)(IRSB*) ); |
| 463 | |
| 464 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 465 | /* ------------------------------------------------------------------ */ |
| 466 | /* Core events to track */ |
| 467 | |
| 468 | /* Part of the core from which this call was made. Useful for determining |
| 469 | what kind of error message should be emitted. */ |
| 470 | typedef |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 471 | enum { Vg_CoreStartup=1, Vg_CoreSignal, Vg_CoreSysCall, |
njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 472 | // This is for platforms where syscall args are passed on the |
| 473 | // stack; although pre_mem_read is the callback that will be |
| 474 | // called, such an arg should be treated (with respect to |
| 475 | // presenting information to the user) as if it was passed in a |
| 476 | // register, ie. like pre_reg_read. |
| 477 | Vg_CoreSysCallArgInMem, |
| 478 | Vg_CoreTranslate, Vg_CoreClientReq |
| 479 | } CorePart; |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 480 | |
| 481 | /* Events happening in core to track. To be notified, pass a callback |
| 482 | function to the appropriate function. To ignore an event, don't do |
| 483 | anything (the default is for events to be ignored). |
| 484 | |
| 485 | Note that most events aren't passed a ThreadId. If the event is one called |
| 486 | from generated code (eg. new_mem_stack_*), you can use |
| 487 | VG_(get_running_tid)() to find it. Otherwise, it has to be passed in, |
| 488 | as in pre_mem_read, and so the event signature will require changing. |
| 489 | |
| 490 | Memory events (Nb: to track heap allocation/freeing, a tool must replace |
| 491 | malloc() et al. See above how to do this.) |
| 492 | |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 493 | These ones occur at startup, upon some signals, and upon some syscalls. |
| 494 | |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 495 | For new_mem_brk and new_mem_stack_signal, the supplied ThreadId |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 496 | indicates the thread for whom the new memory is being allocated. |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 497 | |
| 498 | For new_mem_startup and new_mem_mmap, the di_handle argument is a |
| 499 | handle which can be used to retrieve debug info associated with the |
| 500 | mapping or allocation (because it is of a file that Valgrind has |
| 501 | decided to read debug info from). If the value is zero, there is |
| 502 | no associated debug info. If the value exceeds zero, it can be |
| 503 | supplied as an argument to selected queries in m_debuginfo. |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 504 | */ |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 505 | void VG_(track_new_mem_startup) (void(*f)(Addr a, SizeT len, |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 506 | Bool rr, Bool ww, Bool xx, |
| 507 | ULong di_handle)); |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 508 | void VG_(track_new_mem_stack_signal)(void(*f)(Addr a, SizeT len, ThreadId tid)); |
| 509 | void VG_(track_new_mem_brk) (void(*f)(Addr a, SizeT len, ThreadId tid)); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 510 | void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len, |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 511 | Bool rr, Bool ww, Bool xx, |
| 512 | ULong di_handle)); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 513 | |
| 514 | void VG_(track_copy_mem_remap) (void(*f)(Addr from, Addr to, SizeT len)); |
| 515 | void VG_(track_change_mem_mprotect) (void(*f)(Addr a, SizeT len, |
| 516 | Bool rr, Bool ww, Bool xx)); |
| 517 | void VG_(track_die_mem_stack_signal)(void(*f)(Addr a, SizeT len)); |
| 518 | void VG_(track_die_mem_brk) (void(*f)(Addr a, SizeT len)); |
| 519 | void VG_(track_die_mem_munmap) (void(*f)(Addr a, SizeT len)); |
| 520 | |
| 521 | /* These ones are called when SP changes. A tool could track these itself |
| 522 | (except for ban_mem_stack) but it's much easier to use the core's help. |
| 523 | |
| 524 | The specialised ones are called in preference to the general one, if they |
| 525 | are defined. These functions are called a lot if they are used, so |
| 526 | specialising can optimise things significantly. If any of the |
| 527 | specialised cases are defined, the general case must be defined too. |
| 528 | |
njn | af839f5 | 2005-06-23 03:27:57 +0000 | [diff] [blame] | 529 | Nb: all the specialised ones must use the VG_REGPARM(n) attribute. |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 530 | |
| 531 | For the _new functions, a tool may specify with with-ECU |
| 532 | (ExeContext Unique) or without-ECU version for each size, but not |
| 533 | both. If the with-ECU version is supplied, then the core will |
| 534 | arrange to pass, as the ecu argument, a 32-bit int which uniquely |
| 535 | identifies the instruction moving the stack pointer down. This |
| 536 | 32-bit value is as obtained from VG_(get_ECU_from_ExeContext). |
| 537 | VG_(get_ExeContext_from_ECU) can then be used to retrieve the |
| 538 | associated depth-1 ExeContext for the location. All this |
| 539 | complexity is provided to support origin tracking in Memcheck. |
| 540 | */ |
| 541 | void VG_(track_new_mem_stack_4_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 542 | void VG_(track_new_mem_stack_8_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 543 | void VG_(track_new_mem_stack_12_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 544 | void VG_(track_new_mem_stack_16_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 545 | void VG_(track_new_mem_stack_32_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 546 | void VG_(track_new_mem_stack_112_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 547 | void VG_(track_new_mem_stack_128_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 548 | void VG_(track_new_mem_stack_144_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 549 | void VG_(track_new_mem_stack_160_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu)); |
| 550 | void VG_(track_new_mem_stack_w_ECU) (void(*f)(Addr a, SizeT len, |
| 551 | UInt ecu)); |
| 552 | |
sewardj | f5c8e37 | 2006-02-12 15:42:20 +0000 | [diff] [blame] | 553 | void VG_(track_new_mem_stack_4) (VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 554 | void VG_(track_new_mem_stack_8) (VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 555 | void VG_(track_new_mem_stack_12) (VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 556 | void VG_(track_new_mem_stack_16) (VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 557 | void VG_(track_new_mem_stack_32) (VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 558 | void VG_(track_new_mem_stack_112)(VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 559 | void VG_(track_new_mem_stack_128)(VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 560 | void VG_(track_new_mem_stack_144)(VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 561 | void VG_(track_new_mem_stack_160)(VG_REGPARM(1) void(*f)(Addr new_ESP)); |
| 562 | void VG_(track_new_mem_stack) (void(*f)(Addr a, SizeT len)); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 563 | |
sewardj | f5c8e37 | 2006-02-12 15:42:20 +0000 | [diff] [blame] | 564 | void VG_(track_die_mem_stack_4) (VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 565 | void VG_(track_die_mem_stack_8) (VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 566 | void VG_(track_die_mem_stack_12) (VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 567 | void VG_(track_die_mem_stack_16) (VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 568 | void VG_(track_die_mem_stack_32) (VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 569 | void VG_(track_die_mem_stack_112)(VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 570 | void VG_(track_die_mem_stack_128)(VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 571 | void VG_(track_die_mem_stack_144)(VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 572 | void VG_(track_die_mem_stack_160)(VG_REGPARM(1) void(*f)(Addr die_ESP)); |
| 573 | void VG_(track_die_mem_stack) (void(*f)(Addr a, SizeT len)); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 574 | |
| 575 | /* Used for redzone at end of thread stacks */ |
| 576 | void VG_(track_ban_mem_stack) (void(*f)(Addr a, SizeT len)); |
| 577 | |
| 578 | /* These ones occur around syscalls, signal handling, etc */ |
| 579 | void VG_(track_pre_mem_read) (void(*f)(CorePart part, ThreadId tid, |
| 580 | Char* s, Addr a, SizeT size)); |
| 581 | void VG_(track_pre_mem_read_asciiz)(void(*f)(CorePart part, ThreadId tid, |
| 582 | Char* s, Addr a)); |
| 583 | void VG_(track_pre_mem_write) (void(*f)(CorePart part, ThreadId tid, |
| 584 | Char* s, Addr a, SizeT size)); |
| 585 | void VG_(track_post_mem_write) (void(*f)(CorePart part, ThreadId tid, |
| 586 | Addr a, SizeT size)); |
| 587 | |
| 588 | /* Register events. Use VG_(set_shadow_state_area)() to set the shadow regs |
| 589 | for these events. */ |
| 590 | void VG_(track_pre_reg_read) (void(*f)(CorePart part, ThreadId tid, |
njn | c4431bf | 2009-01-15 21:29:24 +0000 | [diff] [blame] | 591 | Char* s, PtrdiffT guest_state_offset, |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 592 | SizeT size)); |
| 593 | void VG_(track_post_reg_write)(void(*f)(CorePart part, ThreadId tid, |
njn | c4431bf | 2009-01-15 21:29:24 +0000 | [diff] [blame] | 594 | PtrdiffT guest_state_offset, |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 595 | SizeT size)); |
| 596 | |
| 597 | /* This one is called for malloc() et al if they are replaced by a tool. */ |
| 598 | void VG_(track_post_reg_write_clientcall_return)( |
njn | c4431bf | 2009-01-15 21:29:24 +0000 | [diff] [blame] | 599 | void(*f)(ThreadId tid, PtrdiffT guest_state_offset, SizeT size, Addr f)); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 600 | |
| 601 | |
| 602 | /* Scheduler events (not exhaustive) */ |
sewardj | 9756181 | 2006-12-23 01:21:12 +0000 | [diff] [blame] | 603 | |
| 604 | /* Called when 'tid' starts or stops running client code blocks. |
sewardj | adb102f | 2007-11-09 23:21:44 +0000 | [diff] [blame] | 605 | Gives the total dispatched block count at that event. Note, this |
| 606 | is not the same as 'tid' holding the BigLock (the lock that ensures |
| 607 | that only one thread runs at a time): a thread can hold the lock |
| 608 | for other purposes (making translations, etc) yet not be running |
| 609 | client blocks. Obviously though, a thread must hold the lock in |
| 610 | order to run client code blocks, so the times bracketed by |
| 611 | 'start_client_code'..'stop_client_code' are a subset of the times |
| 612 | when thread 'tid' holds the cpu lock. |
sewardj | 9756181 | 2006-12-23 01:21:12 +0000 | [diff] [blame] | 613 | */ |
njn | 3e32c87 | 2006-12-24 07:51:17 +0000 | [diff] [blame] | 614 | void VG_(track_start_client_code)( |
| 615 | void(*f)(ThreadId tid, ULong blocks_dispatched) |
| 616 | ); |
| 617 | void VG_(track_stop_client_code)( |
| 618 | void(*f)(ThreadId tid, ULong blocks_dispatched) |
sewardj | 9756181 | 2006-12-23 01:21:12 +0000 | [diff] [blame] | 619 | ); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 620 | |
| 621 | |
| 622 | /* Thread events (not exhaustive) |
| 623 | |
sewardj | adb102f | 2007-11-09 23:21:44 +0000 | [diff] [blame] | 624 | ll_create: low level thread creation. Called before the new thread |
| 625 | has run any instructions (or touched any memory). In fact, called |
| 626 | immediately before the new thread has come into existence; the new |
| 627 | thread can be assumed to exist when notified by this call. |
| 628 | |
| 629 | ll_exit: low level thread exit. Called after the exiting thread |
| 630 | has run its last instruction. |
sewardj | 29d68f7 | 2007-11-10 22:13:03 +0000 | [diff] [blame] | 631 | |
| 632 | The _ll_ part makes it clear these events are not to do with |
| 633 | pthread_create or pthread_exit/pthread_join (etc), which are a |
sewardj | 391ddf8 | 2007-11-10 22:19:42 +0000 | [diff] [blame] | 634 | higher level abstraction synthesised by libpthread. What you can |
| 635 | be sure of from _ll_create/_ll_exit is the absolute limits of each |
sewardj | 29d68f7 | 2007-11-10 22:13:03 +0000 | [diff] [blame] | 636 | thread's lifetime, and hence be assured that all memory references |
| 637 | made by the thread fall inside the _ll_create/_ll_exit pair. This |
| 638 | is important for tools that need a 100% accurate account of which |
| 639 | thread is responsible for every memory reference in the process. |
| 640 | |
sewardj | 391ddf8 | 2007-11-10 22:19:42 +0000 | [diff] [blame] | 641 | pthread_create/join/exit do not give this property. Calls/returns |
| 642 | to/from them happen arbitrarily far away from the relevant |
| 643 | low-level thread create/quit event. In general a few hundred |
| 644 | instructions; hence a few hundred(ish) memory references could get |
| 645 | misclassified each time. |
sewardj | 7a387ea | 2007-11-25 14:06:06 +0000 | [diff] [blame] | 646 | |
| 647 | pre_thread_first_insn: is called when the thread is all set up and |
| 648 | ready to go (stack in place, etc) but has not executed its first |
| 649 | instruction yet. Gives threading tools a chance to ask questions |
| 650 | about the thread (eg, what is its initial client stack pointer) |
| 651 | that are not easily answered at pre_thread_ll_create time. |
| 652 | |
| 653 | For a given thread, the call sequence is: |
| 654 | ll_create (in the parent's context) |
| 655 | first_insn (in the child's context) |
| 656 | ll_exit (in the child's context) |
sewardj | adb102f | 2007-11-09 23:21:44 +0000 | [diff] [blame] | 657 | */ |
sewardj | 7a387ea | 2007-11-25 14:06:06 +0000 | [diff] [blame] | 658 | void VG_(track_pre_thread_ll_create) (void(*f)(ThreadId tid, ThreadId child)); |
| 659 | void VG_(track_pre_thread_first_insn)(void(*f)(ThreadId tid)); |
| 660 | void VG_(track_pre_thread_ll_exit) (void(*f)(ThreadId tid)); |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 661 | |
njn | 3e32c87 | 2006-12-24 07:51:17 +0000 | [diff] [blame] | 662 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 663 | /* Signal events (not exhaustive) |
| 664 | |
| 665 | ... pre_send_signal, post_send_signal ... |
| 666 | |
| 667 | Called before a signal is delivered; `alt_stack' indicates if it is |
| 668 | delivered on an alternative stack. */ |
| 669 | void VG_(track_pre_deliver_signal) (void(*f)(ThreadId tid, Int sigNo, |
| 670 | Bool alt_stack)); |
| 671 | /* Called after a signal is delivered. Nb: unfortunately, if the signal |
| 672 | handler longjmps, this won't be called. */ |
| 673 | void VG_(track_post_deliver_signal)(void(*f)(ThreadId tid, Int sigNo)); |
| 674 | |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 675 | #endif // __PUB_TOOL_TOOLIFACE_H |
| 676 | |
| 677 | /*--------------------------------------------------------------------*/ |
| 678 | /*--- end ---*/ |
| 679 | /*--------------------------------------------------------------------*/ |