• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- Stuff relating to tool data structures.                      ---*/
4 /*---                                                m_tooliface.c ---*/
5 /*--------------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright (C) 2000-2017 Nicholas Nethercote
12       njn@valgrind.org
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 
32 #include "pub_core_basics.h"
33 #include "pub_core_tooliface.h"
34 #include "pub_core_transtab.h"     /* VG_(ok_to_discard_translations) */
35 
36 // The core/tool dictionary of functions (initially zeroed, as we want it)
37 VgToolInterface VG_(tdict);
38 
39 /*--------------------------------------------------------------------*/
40 /* Setting basic functions */
41 
VG_(basic_tool_funcs)42 void VG_(basic_tool_funcs)(
43    void(*post_clo_init)(void),
44    IRSB*(*instrument)(VgCallbackClosure*, IRSB*,
45                       const VexGuestLayout*, const VexGuestExtents*,
46                       const VexArchInfo*, IRType, IRType),
47    void(*fini)(Int)
48 )
49 {
50    VG_(tdict).tool_post_clo_init = post_clo_init;
51    VG_(tdict).tool_instrument    = instrument;
52    VG_(tdict).tool_fini          = fini;
53 }
54 
55 
56 /*--------------------------------------------------------------------*/
57 /* Setting details */
58 
59 /* Init with default values. */
60 VgDetails VG_(details) = {
61    .name                  = NULL,
62    .version               = NULL,
63    .description           = NULL,
64    .copyright_author      = NULL,
65    .bug_reports_to        = NULL,
66    .avg_translation_sizeB = VG_DEFAULT_TRANS_SIZEB,
67 };
68 
69 /* Use macro because they're so repetitive */
70 #define DETAILS(type, detail)                       \
71    extern void VG_(details_##detail)(type detail)   \
72    {                                                \
73       VG_(details).detail = detail;                 \
74    }
75 
76 DETAILS(const HChar*, name)
77 DETAILS(const HChar*, version)
78 DETAILS(const HChar*, description)
79 DETAILS(const HChar*, copyright_author)
80 DETAILS(const HChar*, bug_reports_to)
81 DETAILS(UInt,  avg_translation_sizeB)
82 
83 
84 /*--------------------------------------------------------------------*/
85 /* Setting needs */
86 
87 VgNeeds VG_(needs) = {
88    .core_errors          = False,
89    .tool_errors          = False,
90    .libc_freeres         = False,
91    .cxx_freeres          = False,
92    .superblock_discards  = False,
93    .command_line_options = False,
94    .client_requests      = False,
95    .syscall_wrapper      = False,
96    .sanity_checks        = False,
97    .print_stats          = False,
98    .info_location        = False,
99    .var_info	         = False,
100    .malloc_replacement   = False,
101    .xml_output           = False,
102    .final_IR_tidy_pass   = False
103 };
104 
105 /* static */
VG_(sanity_check_needs)106 Bool VG_(sanity_check_needs)(const HChar** failmsg)
107 {
108    Bool any_new_mem_stack_N, any_new_mem_stack_N_w_ECU;
109    Bool any_new_mem_stack_w_conflicting_otags;
110    Bool any_die_mem_stack_N;
111 
112 #define CHECK_NOT(var, value)                                  \
113    if ((var)==(value)) {                                       \
114       *failmsg = "Tool error: '" #var "' not initialised\n";   \
115       return False;                                            \
116    }
117 
118    /* Ones that must be set */
119    CHECK_NOT(VG_(details).name,             NULL);
120    /* Nb: .version can be NULL */
121    CHECK_NOT(VG_(details).description,      NULL);
122    CHECK_NOT(VG_(details).copyright_author, NULL);
123    CHECK_NOT(VG_(details).bug_reports_to,   NULL);
124 
125    /* Check that new_mem_stack is defined if any new_mem_stack_N
126       are. */
127    any_new_mem_stack_N
128       = VG_(tdict).track_new_mem_stack_4   ||
129         VG_(tdict).track_new_mem_stack_8   ||
130         VG_(tdict).track_new_mem_stack_12  ||
131         VG_(tdict).track_new_mem_stack_16  ||
132         VG_(tdict).track_new_mem_stack_32  ||
133         VG_(tdict).track_new_mem_stack_112 ||
134         VG_(tdict).track_new_mem_stack_128 ||
135         VG_(tdict).track_new_mem_stack_144 ||
136         VG_(tdict).track_new_mem_stack_160;
137 
138    if (any_new_mem_stack_N && ! VG_(tdict).track_new_mem_stack) {
139       *failmsg = "Tool error: one of the specialised 'new_mem_stack_N'\n"
140                  "   events tracked, but not the generic 'new_mem_stack' one.\n"
141                  "   'new_mem_stack' should be defined\n";
142       return False;
143    }
144 
145    /* Check that new_mem_stack_w_ECU is defined if any
146       new_mem_stack_N_w_ECU are. */
147    any_new_mem_stack_N_w_ECU
148       = VG_(tdict).track_new_mem_stack_4_w_ECU   ||
149         VG_(tdict).track_new_mem_stack_8_w_ECU   ||
150         VG_(tdict).track_new_mem_stack_12_w_ECU  ||
151         VG_(tdict).track_new_mem_stack_16_w_ECU  ||
152         VG_(tdict).track_new_mem_stack_32_w_ECU  ||
153         VG_(tdict).track_new_mem_stack_112_w_ECU ||
154         VG_(tdict).track_new_mem_stack_128_w_ECU ||
155         VG_(tdict).track_new_mem_stack_144_w_ECU ||
156         VG_(tdict).track_new_mem_stack_160_w_ECU;
157 
158    if (any_new_mem_stack_N_w_ECU && ! VG_(tdict).track_new_mem_stack_w_ECU) {
159       *failmsg = "Tool error: one of the specialised 'new_mem_stack_N_w_ECU'\n"
160                  "   events tracked, but not the generic 'new_mem_stack_w_ECU' one.\n"
161                  "   'new_mem_stack_w_ECU' should be defined\n";
162       return False;
163    }
164 
165    /* Check that in no cases are both with- and without-otag versions of the
166       same new_mem_stack_ function defined. */
167    any_new_mem_stack_w_conflicting_otags
168       = (VG_(tdict).track_new_mem_stack_4   && VG_(tdict).track_new_mem_stack_4_w_ECU)   ||
169         (VG_(tdict).track_new_mem_stack_8   && VG_(tdict).track_new_mem_stack_8_w_ECU)   ||
170         (VG_(tdict).track_new_mem_stack_12  && VG_(tdict).track_new_mem_stack_12_w_ECU)  ||
171         (VG_(tdict).track_new_mem_stack_16  && VG_(tdict).track_new_mem_stack_16_w_ECU)  ||
172         (VG_(tdict).track_new_mem_stack_32  && VG_(tdict).track_new_mem_stack_32_w_ECU)  ||
173         (VG_(tdict).track_new_mem_stack_112 && VG_(tdict).track_new_mem_stack_112_w_ECU) ||
174         (VG_(tdict).track_new_mem_stack_128 && VG_(tdict).track_new_mem_stack_128_w_ECU) ||
175         (VG_(tdict).track_new_mem_stack_144 && VG_(tdict).track_new_mem_stack_144_w_ECU) ||
176         (VG_(tdict).track_new_mem_stack_160 && VG_(tdict).track_new_mem_stack_160_w_ECU) ||
177         (VG_(tdict).track_new_mem_stack     && VG_(tdict).track_new_mem_stack_w_ECU);
178 
179    if (any_new_mem_stack_w_conflicting_otags) {
180       *failmsg = "Tool error: tool supplies both a 'new_mem_stack_N' and a\n"
181                  "   'new_mem_stack_N_w_ECU' function for some N (or none),\n"
182                  "   but you can only have one or the other (not both)\n";
183       return False;
184    }
185 
186    /* Check that die_mem_stack is defined if any die_mem_stack_N
187       are. */
188    any_die_mem_stack_N
189       = VG_(tdict).track_die_mem_stack_4   ||
190         VG_(tdict).track_die_mem_stack_8   ||
191         VG_(tdict).track_die_mem_stack_12  ||
192         VG_(tdict).track_die_mem_stack_16  ||
193         VG_(tdict).track_die_mem_stack_32  ||
194         VG_(tdict).track_die_mem_stack_112 ||
195         VG_(tdict).track_die_mem_stack_128 ||
196         VG_(tdict).track_die_mem_stack_144 ||
197         VG_(tdict).track_die_mem_stack_160;
198 
199     if (any_die_mem_stack_N && ! VG_(tdict).track_die_mem_stack) {
200       *failmsg = "Tool error: one of the specialised 'die_mem_stack_N'\n"
201                  "   events tracked, but not the generic 'die_mem_stack' one.\n"
202                  "   'die_mem_stack' should be defined\n";
203       return False;
204    }
205 
206    return True;
207 
208 #undef CHECK_NOT
209 }
210 
211 /* Use macro because they're so repetitive */
212 #define NEEDS(need)  \
213    extern void VG_(needs_##need)(void) \
214    {                                   \
215       VG_(needs).need = True;          \
216    }
217 
218 // These ones don't require any tool-supplied functions
219 NEEDS(libc_freeres)
NEEDS(cxx_freeres)220 NEEDS(cxx_freeres)
221 NEEDS(core_errors)
222 NEEDS(var_info)
223 
224 void VG_(needs_superblock_discards)(
225    void (*discard)(Addr, VexGuestExtents)
226 )
227 {
228    VG_(needs).superblock_discards = True;
229    VG_(tdict).tool_discard_superblock_info = discard;
230 }
231 
VG_(needs_tool_errors)232 void VG_(needs_tool_errors)(
233    Bool (*eq)         (VgRes, const Error*, const Error*),
234    void (*before_pp)  (const Error*),
235    void (*pp)         (const Error*),
236    Bool show_TIDs,
237    UInt (*update)     (const Error*),
238    Bool (*recog)      (const HChar*, Supp*),
239    Bool (*read_extra) (Int, HChar**, SizeT*, Int*, Supp*),
240    Bool (*matches)    (const Error*, const Supp*),
241    const HChar* (*name) (const Error*),
242    SizeT (*get_xtra_si)(const Error*,/*OUT*/HChar*,Int),
243    SizeT (*print_xtra_su)(const Supp*,/*OUT*/HChar*,Int),
244    void (*update_xtra_su)(const Error*, const Supp*)
245 )
246 {
247    VG_(needs).tool_errors = True;
248    VG_(tdict).tool_eq_Error                     = eq;
249    VG_(tdict).tool_before_pp_Error              = before_pp;
250    VG_(tdict).tool_pp_Error                     = pp;
251    VG_(tdict).tool_show_ThreadIDs_for_errors    = show_TIDs;
252    VG_(tdict).tool_update_extra                 = update;
253    VG_(tdict).tool_recognised_suppression       = recog;
254    VG_(tdict).tool_read_extra_suppression_info  = read_extra;
255    VG_(tdict).tool_error_matches_suppression    = matches;
256    VG_(tdict).tool_get_error_name               = name;
257    VG_(tdict).tool_get_extra_suppression_info   = get_xtra_si;
258    VG_(tdict).tool_print_extra_suppression_use  = print_xtra_su;
259    VG_(tdict).tool_update_extra_suppression_use = update_xtra_su;
260 }
261 
VG_(needs_command_line_options)262 void VG_(needs_command_line_options)(
263    Bool (*process)(const HChar*),
264    void (*usage)(void),
265    void (*debug_usage)(void)
266 )
267 {
268    VG_(needs).command_line_options = True;
269    VG_(tdict).tool_process_cmd_line_option = process;
270    VG_(tdict).tool_print_usage             = usage;
271    VG_(tdict).tool_print_debug_usage       = debug_usage;
272 }
273 
274 /* The tool's function for handling client requests. */
275 static Bool (*tool_handle_client_request_func)(ThreadId, UWord *, UWord *);
276 
wrap_tool_handle_client_request(ThreadId tid,UWord * arg1,UWord * arg2)277 static Bool wrap_tool_handle_client_request(ThreadId tid, UWord *arg1,
278                                             UWord *arg2)
279 {
280    Bool ret;
281    VG_(ok_to_discard_translations) = True;
282    ret = tool_handle_client_request_func(tid, arg1, arg2);
283    VG_(ok_to_discard_translations) = False;
284    return ret;
285 }
286 
VG_(needs_client_requests)287 void VG_(needs_client_requests)(
288    Bool (*handle)(ThreadId, UWord*, UWord*)
289 )
290 {
291    VG_(needs).client_requests = True;
292    tool_handle_client_request_func = handle;   /* Stash away */
293    /* Register the wrapper function */
294    VG_(tdict).tool_handle_client_request = wrap_tool_handle_client_request;
295 }
296 
VG_(needs_syscall_wrapper)297 void VG_(needs_syscall_wrapper)(
298    void(*pre) (ThreadId, UInt, UWord*, UInt),
299    void(*post)(ThreadId, UInt, UWord*, UInt, SysRes res)
300 )
301 {
302    VG_(needs).syscall_wrapper = True;
303    VG_(tdict).tool_pre_syscall  = pre;
304    VG_(tdict).tool_post_syscall = post;
305 }
306 
VG_(needs_sanity_checks)307 void VG_(needs_sanity_checks)(
308    Bool(*cheap)(void),
309    Bool(*expen)(void)
310 )
311 {
312    VG_(needs).sanity_checks = True;
313    VG_(tdict).tool_cheap_sanity_check     = cheap;
314    VG_(tdict).tool_expensive_sanity_check = expen;
315 }
316 
VG_(needs_print_stats)317 void VG_(needs_print_stats) (
318    void (*print_stats)(void)
319 )
320 {
321    VG_(needs).print_stats = True;
322    VG_(tdict).tool_print_stats = print_stats;
323 }
324 
VG_(needs_info_location)325 void VG_(needs_info_location) (
326    void (*info_location)(Addr)
327 )
328 {
329    VG_(needs).info_location = True;
330    VG_(tdict).tool_info_location = info_location;
331 }
332 
VG_(needs_malloc_replacement)333 void VG_(needs_malloc_replacement)(
334    void* (*malloc)               ( ThreadId, SizeT ),
335    void* (*__builtin_new)        ( ThreadId, SizeT ),
336    void* (*__builtin_vec_new)    ( ThreadId, SizeT ),
337    void* (*memalign)             ( ThreadId, SizeT, SizeT ),
338    void* (*calloc)               ( ThreadId, SizeT, SizeT ),
339    void  (*free)                 ( ThreadId, void* ),
340    void  (*__builtin_delete)     ( ThreadId, void* ),
341    void  (*__builtin_vec_delete) ( ThreadId, void* ),
342    void* (*realloc)              ( ThreadId, void*, SizeT ),
343    SizeT (*malloc_usable_size)   ( ThreadId, void* ),
344    SizeT client_malloc_redzone_szB
345 )
346 {
347    VG_(needs).malloc_replacement        = True;
348    VG_(tdict).tool_malloc               = malloc;
349    VG_(tdict).tool___builtin_new        = __builtin_new;
350    VG_(tdict).tool___builtin_vec_new    = __builtin_vec_new;
351    VG_(tdict).tool_memalign             = memalign;
352    VG_(tdict).tool_calloc               = calloc;
353    VG_(tdict).tool_free                 = free;
354    VG_(tdict).tool___builtin_delete     = __builtin_delete;
355    VG_(tdict).tool___builtin_vec_delete = __builtin_vec_delete;
356    VG_(tdict).tool_realloc              = realloc;
357    VG_(tdict).tool_malloc_usable_size   = malloc_usable_size;
358    VG_(tdict).tool_client_redzone_szB   = client_malloc_redzone_szB;
359 }
360 
VG_(needs_xml_output)361 void VG_(needs_xml_output)( void )
362 {
363    VG_(needs).xml_output = True;
364 }
365 
VG_(needs_final_IR_tidy_pass)366 void VG_(needs_final_IR_tidy_pass)(
367    IRSB*(*final_tidy)(IRSB*)
368 )
369 {
370    VG_(needs).final_IR_tidy_pass = True;
371    VG_(tdict).tool_final_IR_tidy_pass = final_tidy;
372 }
373 
374 /*--------------------------------------------------------------------*/
375 /* Tracked events.  Digit 'n' on DEFn is the REGPARMness. */
376 
377 #define DEF0(fn, args...) \
378 void VG_(fn)(void(*f)(args)) { \
379    VG_(tdict).fn = f; \
380 }
381 
382 #define DEF1(fn, args...) \
383 void VG_(fn)(VG_REGPARM(1) void(*f)(args)) { \
384    VG_(tdict).fn = f; \
385 }
386 
387 #define DEF2(fn, args...) \
388 void VG_(fn)(VG_REGPARM(2) void(*f)(args)) { \
389    VG_(tdict).fn = f; \
390 }
391 
392 DEF0(track_new_mem_startup,       Addr, SizeT, Bool, Bool, Bool, ULong)
393 DEF0(track_new_mem_stack_signal,  Addr, SizeT, UInt)
394 DEF0(track_new_mem_brk,           Addr, SizeT, UInt)
395 DEF0(track_new_mem_mmap,          Addr, SizeT, Bool, Bool, Bool, ULong)
396 
397 DEF0(track_copy_mem_remap,        Addr, Addr, SizeT)
398 DEF0(track_change_mem_mprotect,   Addr, SizeT, Bool, Bool, Bool)
399 DEF0(track_die_mem_stack_signal,  Addr, SizeT)
400 DEF0(track_die_mem_brk,           Addr, SizeT)
401 DEF0(track_die_mem_munmap,        Addr, SizeT)
402 
403 DEF2(track_new_mem_stack_4_w_ECU,    Addr, UInt)
404 DEF2(track_new_mem_stack_8_w_ECU,    Addr, UInt)
405 DEF2(track_new_mem_stack_12_w_ECU,   Addr, UInt)
406 DEF2(track_new_mem_stack_16_w_ECU,   Addr, UInt)
407 DEF2(track_new_mem_stack_32_w_ECU,   Addr, UInt)
408 DEF2(track_new_mem_stack_112_w_ECU,  Addr, UInt)
409 DEF2(track_new_mem_stack_128_w_ECU,  Addr, UInt)
410 DEF2(track_new_mem_stack_144_w_ECU,  Addr, UInt)
411 DEF2(track_new_mem_stack_160_w_ECU,  Addr, UInt)
412 DEF0(track_new_mem_stack_w_ECU,      Addr, SizeT, UInt)
413 
414 DEF1(track_new_mem_stack_4,       Addr)
415 DEF1(track_new_mem_stack_8,       Addr)
416 DEF1(track_new_mem_stack_12,      Addr)
417 DEF1(track_new_mem_stack_16,      Addr)
418 DEF1(track_new_mem_stack_32,      Addr)
419 DEF1(track_new_mem_stack_112,     Addr)
420 DEF1(track_new_mem_stack_128,     Addr)
421 DEF1(track_new_mem_stack_144,     Addr)
422 DEF1(track_new_mem_stack_160,     Addr)
423 DEF0(track_new_mem_stack,         Addr, SizeT)
424 
425 DEF1(track_die_mem_stack_4,       Addr)
426 DEF1(track_die_mem_stack_8,       Addr)
427 DEF1(track_die_mem_stack_12,      Addr)
428 DEF1(track_die_mem_stack_16,      Addr)
429 DEF1(track_die_mem_stack_32,      Addr)
430 DEF1(track_die_mem_stack_112,     Addr)
431 DEF1(track_die_mem_stack_128,     Addr)
432 DEF1(track_die_mem_stack_144,     Addr)
433 DEF1(track_die_mem_stack_160,     Addr)
434 DEF0(track_die_mem_stack,         Addr, SizeT)
435 
436 DEF0(track_ban_mem_stack,         Addr, SizeT)
437 
438 DEF0(track_pre_mem_read,          CorePart, ThreadId, const HChar*, Addr, SizeT)
439 DEF0(track_pre_mem_read_asciiz,   CorePart, ThreadId, const HChar*, Addr)
440 DEF0(track_pre_mem_write,         CorePart, ThreadId, const HChar*, Addr, SizeT)
441 DEF0(track_post_mem_write,        CorePart, ThreadId, Addr, SizeT)
442 
443 DEF0(track_pre_reg_read,          CorePart, ThreadId, const HChar*, PtrdiffT, SizeT)
444 DEF0(track_post_reg_write,        CorePart, ThreadId,               PtrdiffT, SizeT)
445 
446 DEF0(track_copy_mem_to_reg,       CorePart, ThreadId, Addr, PtrdiffT, SizeT)
447 DEF0(track_copy_reg_to_mem,       CorePart, ThreadId, PtrdiffT, Addr, SizeT)
448 
449 DEF0(track_post_reg_write_clientcall_return, ThreadId, PtrdiffT, SizeT, Addr)
450 
451 DEF0(track_start_client_code,     ThreadId, ULong)
452 DEF0(track_stop_client_code,      ThreadId, ULong)
453 
454 DEF0(track_pre_thread_ll_create,  ThreadId, ThreadId)
455 DEF0(track_pre_thread_first_insn, ThreadId)
456 DEF0(track_pre_thread_ll_exit,    ThreadId)
457 
458 DEF0(track_pre_deliver_signal,    ThreadId, Int sigNo, Bool)
459 DEF0(track_post_deliver_signal,   ThreadId, Int sigNo)
460 
461 /*--------------------------------------------------------------------*/
462 /*--- end                                                          ---*/
463 /*--------------------------------------------------------------------*/
464