2 /*--------------------------------------------------------------------*/
3 /*--- Stuff relating to tool data structures. ---*/
4 /*--- m_tooliface.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2017 Nicholas Nethercote
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #include "pub_core_basics.h"
31 #include "pub_core_tooliface.h"
32 #include "pub_core_transtab.h" /* VG_(ok_to_discard_translations) */
34 // The core/tool dictionary of functions (initially zeroed, as we want it)
35 VgToolInterface
VG_(tdict
);
37 /*--------------------------------------------------------------------*/
38 /* Setting basic functions */
40 void VG_(basic_tool_funcs
)(
41 void(*post_clo_init
)(void),
42 IRSB
*(*instrument
)(VgCallbackClosure
*, IRSB
*,
43 const VexGuestLayout
*, const VexGuestExtents
*,
44 const VexArchInfo
*, IRType
, IRType
),
48 VG_(tdict
).tool_post_clo_init
= post_clo_init
;
49 VG_(tdict
).tool_instrument
= instrument
;
50 VG_(tdict
).tool_fini
= fini
;
54 /*--------------------------------------------------------------------*/
57 /* Init with default values. */
58 VgDetails
VG_(details
) = {
62 .copyright_author
= NULL
,
63 .bug_reports_to
= NULL
,
64 .avg_translation_sizeB
= VG_DEFAULT_TRANS_SIZEB
,
67 /* Use macro because they're so repetitive */
68 #define DETAILS(type, detail) \
69 extern void VG_(details_##detail)(type detail) \
71 VG_(details).detail = detail; \
74 DETAILS(const HChar
*, name
)
75 DETAILS(const HChar
*, version
)
76 DETAILS(const HChar
*, description
)
77 DETAILS(const HChar
*, copyright_author
)
78 DETAILS(const HChar
*, bug_reports_to
)
79 DETAILS(UInt
, avg_translation_sizeB
)
82 /*--------------------------------------------------------------------*/
85 VgNeeds
VG_(needs
) = {
88 .libc_freeres
= False
,
90 .superblock_discards
= False
,
91 .command_line_options
= False
,
92 .client_requests
= False
,
93 .syscall_wrapper
= False
,
94 .sanity_checks
= False
,
96 .info_location
= False
,
98 .malloc_replacement
= False
,
100 .final_IR_tidy_pass
= False
104 Bool
VG_(finish_needs_init
)(const HChar
** failmsg
)
106 Bool any_new_mem_stack_N
, any_new_mem_stack_N_w_ECU
;
107 Bool any_new_mem_stack_w_conflicting_otags
;
108 Bool any_die_mem_stack_N
;
110 #define CHECK_NOT(var, value) \
111 if ((var)==(value)) { \
112 *failmsg = "Tool error: '" #var "' not initialised\n"; \
116 /* Ones that must be set */
117 CHECK_NOT(VG_(details
).name
, NULL
);
118 /* Nb: .version can be NULL */
119 CHECK_NOT(VG_(details
).description
, NULL
);
120 CHECK_NOT(VG_(details
).copyright_author
, NULL
);
121 CHECK_NOT(VG_(details
).bug_reports_to
, NULL
);
123 /* Check that new_mem_stack is defined if any new_mem_stack_N
126 = VG_(tdict
).track_new_mem_stack_4
||
127 VG_(tdict
).track_new_mem_stack_8
||
128 VG_(tdict
).track_new_mem_stack_12
||
129 VG_(tdict
).track_new_mem_stack_16
||
130 VG_(tdict
).track_new_mem_stack_32
||
131 VG_(tdict
).track_new_mem_stack_112
||
132 VG_(tdict
).track_new_mem_stack_128
||
133 VG_(tdict
).track_new_mem_stack_144
||
134 VG_(tdict
).track_new_mem_stack_160
;
136 if (any_new_mem_stack_N
&& ! VG_(tdict
).track_new_mem_stack
) {
137 *failmsg
= "Tool error: one of the specialised 'new_mem_stack_N'\n"
138 " events tracked, but not the generic 'new_mem_stack' one.\n"
139 " 'new_mem_stack' should be defined\n";
143 /* Check that new_mem_stack_w_ECU is defined if any
144 new_mem_stack_N_w_ECU are. */
145 any_new_mem_stack_N_w_ECU
146 = VG_(tdict
).track_new_mem_stack_4_w_ECU
||
147 VG_(tdict
).track_new_mem_stack_8_w_ECU
||
148 VG_(tdict
).track_new_mem_stack_12_w_ECU
||
149 VG_(tdict
).track_new_mem_stack_16_w_ECU
||
150 VG_(tdict
).track_new_mem_stack_32_w_ECU
||
151 VG_(tdict
).track_new_mem_stack_112_w_ECU
||
152 VG_(tdict
).track_new_mem_stack_128_w_ECU
||
153 VG_(tdict
).track_new_mem_stack_144_w_ECU
||
154 VG_(tdict
).track_new_mem_stack_160_w_ECU
;
156 if (any_new_mem_stack_N_w_ECU
&& ! VG_(tdict
).track_new_mem_stack_w_ECU
) {
157 *failmsg
= "Tool error: one of the specialised 'new_mem_stack_N_w_ECU'\n"
158 " events tracked, but not the generic 'new_mem_stack_w_ECU' one.\n"
159 " 'new_mem_stack_w_ECU' should be defined\n";
163 /* Check that in no cases are both with- and without-otag versions of the
164 same new_mem_stack_ function defined. */
165 any_new_mem_stack_w_conflicting_otags
166 = (VG_(tdict
).track_new_mem_stack_4
&& VG_(tdict
).track_new_mem_stack_4_w_ECU
) ||
167 (VG_(tdict
).track_new_mem_stack_8
&& VG_(tdict
).track_new_mem_stack_8_w_ECU
) ||
168 (VG_(tdict
).track_new_mem_stack_12
&& VG_(tdict
).track_new_mem_stack_12_w_ECU
) ||
169 (VG_(tdict
).track_new_mem_stack_16
&& VG_(tdict
).track_new_mem_stack_16_w_ECU
) ||
170 (VG_(tdict
).track_new_mem_stack_32
&& VG_(tdict
).track_new_mem_stack_32_w_ECU
) ||
171 (VG_(tdict
).track_new_mem_stack_112
&& VG_(tdict
).track_new_mem_stack_112_w_ECU
) ||
172 (VG_(tdict
).track_new_mem_stack_128
&& VG_(tdict
).track_new_mem_stack_128_w_ECU
) ||
173 (VG_(tdict
).track_new_mem_stack_144
&& VG_(tdict
).track_new_mem_stack_144_w_ECU
) ||
174 (VG_(tdict
).track_new_mem_stack_160
&& VG_(tdict
).track_new_mem_stack_160_w_ECU
) ||
175 (VG_(tdict
).track_new_mem_stack
&& VG_(tdict
).track_new_mem_stack_w_ECU
);
177 if (any_new_mem_stack_w_conflicting_otags
) {
178 *failmsg
= "Tool error: tool supplies both a 'new_mem_stack_N' and a\n"
179 " 'new_mem_stack_N_w_ECU' function for some N (or none),\n"
180 " but you can only have one or the other (not both)\n";
183 VG_(tdict
).any_new_mem_stack
184 = VG_(tdict
).track_new_mem_stack
|| VG_(tdict
).track_new_mem_stack_w_ECU
185 || any_new_mem_stack_N
|| any_new_mem_stack_N_w_ECU
;
187 /* Check that die_mem_stack is defined if any die_mem_stack_N
190 = VG_(tdict
).track_die_mem_stack_4
||
191 VG_(tdict
).track_die_mem_stack_8
||
192 VG_(tdict
).track_die_mem_stack_12
||
193 VG_(tdict
).track_die_mem_stack_16
||
194 VG_(tdict
).track_die_mem_stack_32
||
195 VG_(tdict
).track_die_mem_stack_112
||
196 VG_(tdict
).track_die_mem_stack_128
||
197 VG_(tdict
).track_die_mem_stack_144
||
198 VG_(tdict
).track_die_mem_stack_160
;
200 if (any_die_mem_stack_N
&& ! VG_(tdict
).track_die_mem_stack
) {
201 *failmsg
= "Tool error: one of the specialised 'die_mem_stack_N'\n"
202 " events tracked, but not the generic 'die_mem_stack' one.\n"
203 " 'die_mem_stack' should be defined\n";
206 VG_(tdict
).any_die_mem_stack
207 = VG_(tdict
).track_die_mem_stack
|| any_die_mem_stack_N
;
214 /* Use macro because they're so repetitive */
215 #define NEEDS(need) \
216 extern void VG_(needs_##need)(void) \
218 VG_(needs).need = True; \
221 // These ones don't require any tool-supplied functions
227 void VG_(needs_superblock_discards
)(
228 void (*discard
)(Addr
, VexGuestExtents
)
231 VG_(needs
).superblock_discards
= True
;
232 VG_(tdict
).tool_discard_superblock_info
= discard
;
235 void VG_(needs_tool_errors
)(
236 Bool (*eq
) (VgRes
, const Error
*, const Error
*),
237 void (*before_pp
) (const Error
*),
238 void (*pp
) (const Error
*),
240 UInt (*update
) (const Error
*),
241 Bool (*recog
) (const HChar
*, Supp
*),
242 Bool (*read_extra
) (Int
, HChar
**, SizeT
*, Int
*, Supp
*),
243 Bool (*matches
) (const Error
*, const Supp
*),
244 const HChar
* (*name
) (const Error
*),
245 SizeT (*get_xtra_si
)(const Error
*,/*OUT*/HChar
*,Int
),
246 SizeT (*print_xtra_su
)(const Supp
*,/*OUT*/HChar
*,Int
),
247 void (*update_xtra_su
)(const Error
*, const Supp
*)
250 VG_(needs
).tool_errors
= True
;
251 VG_(tdict
).tool_eq_Error
= eq
;
252 VG_(tdict
).tool_before_pp_Error
= before_pp
;
253 VG_(tdict
).tool_pp_Error
= pp
;
254 VG_(tdict
).tool_show_ThreadIDs_for_errors
= show_TIDs
;
255 VG_(tdict
).tool_update_extra
= update
;
256 VG_(tdict
).tool_recognised_suppression
= recog
;
257 VG_(tdict
).tool_read_extra_suppression_info
= read_extra
;
258 VG_(tdict
).tool_error_matches_suppression
= matches
;
259 VG_(tdict
).tool_get_error_name
= name
;
260 VG_(tdict
).tool_get_extra_suppression_info
= get_xtra_si
;
261 VG_(tdict
).tool_print_extra_suppression_use
= print_xtra_su
;
262 VG_(tdict
).tool_update_extra_suppression_use
= update_xtra_su
;
265 void VG_(needs_command_line_options
)(
266 Bool (*process
)(const HChar
*),
268 void (*debug_usage
)(void)
271 VG_(needs
).command_line_options
= True
;
272 VG_(tdict
).tool_process_cmd_line_option
= process
;
273 VG_(tdict
).tool_print_usage
= usage
;
274 VG_(tdict
).tool_print_debug_usage
= debug_usage
;
277 /* The tool's function for handling client requests. */
278 static Bool (*tool_handle_client_request_func
)(ThreadId
, UWord
*, UWord
*);
280 static Bool
wrap_tool_handle_client_request(ThreadId tid
, UWord
*arg1
,
284 VG_(ok_to_discard_translations
) = True
;
285 ret
= tool_handle_client_request_func(tid
, arg1
, arg2
);
286 VG_(ok_to_discard_translations
) = False
;
290 void VG_(needs_client_requests
)(
291 Bool (*handle
)(ThreadId
, UWord
*, UWord
*)
294 VG_(needs
).client_requests
= True
;
295 tool_handle_client_request_func
= handle
; /* Stash away */
296 /* Register the wrapper function */
297 VG_(tdict
).tool_handle_client_request
= wrap_tool_handle_client_request
;
300 void VG_(needs_syscall_wrapper
)(
301 void(*pre
) (ThreadId
, UInt
, UWord
*, UInt
),
302 void(*post
)(ThreadId
, UInt
, UWord
*, UInt
, SysRes res
)
305 VG_(needs
).syscall_wrapper
= True
;
306 VG_(tdict
).tool_pre_syscall
= pre
;
307 VG_(tdict
).tool_post_syscall
= post
;
310 void VG_(needs_sanity_checks
)(
315 VG_(needs
).sanity_checks
= True
;
316 VG_(tdict
).tool_cheap_sanity_check
= cheap
;
317 VG_(tdict
).tool_expensive_sanity_check
= expen
;
320 void VG_(needs_print_stats
) (
321 void (*print_stats
)(void)
324 VG_(needs
).print_stats
= True
;
325 VG_(tdict
).tool_print_stats
= print_stats
;
328 void VG_(needs_info_location
) (
329 void (*info_location
)(DiEpoch
, Addr
)
332 VG_(needs
).info_location
= True
;
333 VG_(tdict
).tool_info_location
= info_location
;
336 void VG_(needs_malloc_replacement
)(
337 void* (*malloc
) ( ThreadId
, SizeT
),
338 void* (*__builtin_new
) ( ThreadId
, SizeT
),
339 void* (*__builtin_new_aligned
)( ThreadId
, SizeT
, SizeT
, SizeT
),
340 void* (*__builtin_vec_new
) ( ThreadId
, SizeT
),
341 void* (*__builtin_vec_new_aligned
)( ThreadId
, SizeT
, SizeT
, SizeT
),
342 void* (*memalign
) ( ThreadId
, SizeT
, SizeT
, SizeT
),
343 void* (*calloc
) ( ThreadId
, SizeT
, SizeT
),
344 void (*free
) ( ThreadId
, void* ),
345 void (*__builtin_delete
) ( ThreadId
, void* ),
346 void (*__builtin_delete_aligned
) ( ThreadId
, void*, SizeT
),
347 void (*__builtin_vec_delete
) ( ThreadId
, void* ),
348 void (*__builtin_vec_delete_aligned
) ( ThreadId
, void*, SizeT
),
349 void* (*realloc
) ( ThreadId
, void*, SizeT
),
350 SizeT (*malloc_usable_size
) ( ThreadId
, void* ),
351 SizeT client_malloc_redzone_szB
354 VG_(needs
).malloc_replacement
= True
;
355 VG_(tdict
).tool_malloc
= malloc
;
356 VG_(tdict
).tool___builtin_new
= __builtin_new
;
357 VG_(tdict
).tool___builtin_new_aligned
= __builtin_new_aligned
;
358 VG_(tdict
).tool___builtin_vec_new
= __builtin_vec_new
;
359 VG_(tdict
).tool___builtin_vec_new_aligned
= __builtin_vec_new_aligned
;
360 VG_(tdict
).tool_memalign
= memalign
;
361 VG_(tdict
).tool_calloc
= calloc
;
362 VG_(tdict
).tool_free
= free
;
363 VG_(tdict
).tool___builtin_delete
= __builtin_delete
;
364 VG_(tdict
).tool___builtin_delete_aligned
= __builtin_delete_aligned
;
365 VG_(tdict
).tool___builtin_vec_delete
= __builtin_vec_delete
;
366 VG_(tdict
).tool___builtin_vec_delete_aligned
= __builtin_vec_delete_aligned
;
367 VG_(tdict
).tool_realloc
= realloc
;
368 VG_(tdict
).tool_malloc_usable_size
= malloc_usable_size
;
369 VG_(tdict
).tool_client_redzone_szB
= client_malloc_redzone_szB
;
372 void VG_(needs_xml_output
)( void )
374 VG_(needs
).xml_output
= True
;
377 void VG_(needs_final_IR_tidy_pass
)(
378 IRSB
*(*final_tidy
)(IRSB
*)
381 VG_(needs
).final_IR_tidy_pass
= True
;
382 VG_(tdict
).tool_final_IR_tidy_pass
= final_tidy
;
385 /*--------------------------------------------------------------------*/
386 /* Tracked events. Digit 'n' on DEFn is the REGPARMness. */
388 #define DEF0(fn, args...) \
389 void VG_(fn)(void(*f)(args)) { \
393 #define DEF1(fn, args...) \
394 void VG_(fn)(VG_REGPARM(1) void(*f)(args)) { \
398 #define DEF2(fn, args...) \
399 void VG_(fn)(VG_REGPARM(2) void(*f)(args)) { \
403 DEF0(track_new_mem_startup
, Addr
, SizeT
, Bool
, Bool
, Bool
, ULong
)
404 DEF0(track_new_mem_stack_signal
, Addr
, SizeT
, UInt
)
405 DEF0(track_new_mem_brk
, Addr
, SizeT
, UInt
)
406 DEF0(track_new_mem_mmap
, Addr
, SizeT
, Bool
, Bool
, Bool
, ULong
)
408 DEF0(track_copy_mem_remap
, Addr
, Addr
, SizeT
)
409 DEF0(track_change_mem_mprotect
, Addr
, SizeT
, Bool
, Bool
, Bool
)
410 DEF0(track_die_mem_stack_signal
, Addr
, SizeT
)
411 DEF0(track_die_mem_brk
, Addr
, SizeT
)
412 DEF0(track_die_mem_munmap
, Addr
, SizeT
)
414 DEF2(track_new_mem_stack_4_w_ECU
, Addr
, UInt
)
415 DEF2(track_new_mem_stack_8_w_ECU
, Addr
, UInt
)
416 DEF2(track_new_mem_stack_12_w_ECU
, Addr
, UInt
)
417 DEF2(track_new_mem_stack_16_w_ECU
, Addr
, UInt
)
418 DEF2(track_new_mem_stack_32_w_ECU
, Addr
, UInt
)
419 DEF2(track_new_mem_stack_112_w_ECU
, Addr
, UInt
)
420 DEF2(track_new_mem_stack_128_w_ECU
, Addr
, UInt
)
421 DEF2(track_new_mem_stack_144_w_ECU
, Addr
, UInt
)
422 DEF2(track_new_mem_stack_160_w_ECU
, Addr
, UInt
)
423 DEF0(track_new_mem_stack_w_ECU
, Addr
, SizeT
, UInt
)
425 DEF1(track_new_mem_stack_4
, Addr
)
426 DEF1(track_new_mem_stack_8
, Addr
)
427 DEF1(track_new_mem_stack_12
, Addr
)
428 DEF1(track_new_mem_stack_16
, Addr
)
429 DEF1(track_new_mem_stack_32
, Addr
)
430 DEF1(track_new_mem_stack_112
, Addr
)
431 DEF1(track_new_mem_stack_128
, Addr
)
432 DEF1(track_new_mem_stack_144
, Addr
)
433 DEF1(track_new_mem_stack_160
, Addr
)
434 DEF0(track_new_mem_stack
, Addr
, SizeT
)
436 DEF1(track_die_mem_stack_4
, Addr
)
437 DEF1(track_die_mem_stack_8
, Addr
)
438 DEF1(track_die_mem_stack_12
, Addr
)
439 DEF1(track_die_mem_stack_16
, Addr
)
440 DEF1(track_die_mem_stack_32
, Addr
)
441 DEF1(track_die_mem_stack_112
, Addr
)
442 DEF1(track_die_mem_stack_128
, Addr
)
443 DEF1(track_die_mem_stack_144
, Addr
)
444 DEF1(track_die_mem_stack_160
, Addr
)
445 DEF0(track_die_mem_stack
, Addr
, SizeT
)
447 DEF0(track_ban_mem_stack
, Addr
, SizeT
)
449 DEF0(track_register_stack
, Addr
, Addr
)
451 DEF0(track_pre_mem_read
, CorePart
, ThreadId
, const HChar
*, Addr
, SizeT
)
452 DEF0(track_pre_mem_read_asciiz
, CorePart
, ThreadId
, const HChar
*, Addr
)
453 DEF0(track_pre_mem_write
, CorePart
, ThreadId
, const HChar
*, Addr
, SizeT
)
454 DEF0(track_post_mem_write
, CorePart
, ThreadId
, Addr
, SizeT
)
456 DEF0(track_pre_reg_read
, CorePart
, ThreadId
, const HChar
*, PtrdiffT
, SizeT
)
457 DEF0(track_post_reg_write
, CorePart
, ThreadId
, PtrdiffT
, SizeT
)
459 DEF0(track_copy_mem_to_reg
, CorePart
, ThreadId
, Addr
, PtrdiffT
, SizeT
)
460 DEF0(track_copy_reg_to_mem
, CorePart
, ThreadId
, PtrdiffT
, Addr
, SizeT
)
462 DEF0(track_post_reg_write_clientcall_return
, ThreadId
, PtrdiffT
, SizeT
, Addr
)
464 DEF0(track_start_client_code
, ThreadId
, ULong
)
465 DEF0(track_stop_client_code
, ThreadId
, ULong
)
467 DEF0(track_pre_thread_ll_create
, ThreadId
, ThreadId
)
468 DEF0(track_pre_thread_first_insn
, ThreadId
)
469 DEF0(track_pre_thread_ll_exit
, ThreadId
)
471 DEF0(track_pre_deliver_signal
, ThreadId
, Int sigNo
, Bool
)
472 DEF0(track_post_deliver_signal
, ThreadId
, Int sigNo
)
474 /*--------------------------------------------------------------------*/
476 /*--------------------------------------------------------------------*/