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