-
Notifications
You must be signed in to change notification settings - Fork 571
/
Copy pathinstrument_api.h
6890 lines (6425 loc) · 273 KB
/
instrument_api.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* **********************************************************
* Copyright (c) 2010-2020 Google, Inc. All rights reserved.
* Copyright (c) 2002-2010 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
/* Copyright (c) 2003-2007 Determina Corp. */
/* Copyright (c) 2002-2003 Massachusetts Institute of Technology */
/* Copyright (c) 2002 Hewlett-Packard Company */
/*
* instrument_api.h - exposed API for instrumentation
*/
#ifndef _INSTRUMENT_API_H_
#define _INSTRUMENT_API_H_ 1
#include "../globals.h"
#include "../module_shared.h"
#include "arch.h"
#include "instr.h"
#include "dr_config.h"
#ifdef CLIENT_INTERFACE
/* DR_API EXPORT TOFILE dr_events.h */
/* DR_API EXPORT BEGIN */
# ifdef API_EXPORT_ONLY
# include "dr_config.h"
# endif
/**************************************************
* ROUTINES TO REGISTER EVENT CALLBACKS
*/
/**
* @file dr_events.h
* @brief Event callback registration routines.
*/
/* DR_API EXPORT END */
DR_API
/**
* Registers a callback function for the process exit event. DR calls \p
* func when the process exits. By default, the process exit event will be
* executed with only a single live thread. dr_set_process_exit_behavior()
* can provide superior exit performance for clients that have flexible
* exit event requirements.
*
* On Linux, SYS_execve does NOT result in an exit event, but it WILL
* result in the client library being reloaded and its dr_client_main()
* routine being called.
*/
void
dr_register_exit_event(void (*func)(void));
DR_API
/**
* Unregister a callback function for the process exit event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
dr_unregister_exit_event(void (*func)(void));
/* DR_API EXPORT TOFILE dr_events.h */
/* DR_API EXPORT BEGIN */
/**
* Flags controlling the behavior of basic blocks and traces when emitted
* into the code cache. These flags are bitmasks that can be combined by
* or-ing together. For multiple clients, the flags returned by each
* client are or-ed together.
*/
typedef enum {
/** Emit as normal. */
DR_EMIT_DEFAULT = 0,
/**
* Store translation information at emit time rather than calling
* the basic block or trace event later to recreate the
* information. Note that even if a standalone basic block has
* stored translations, if when it is added to a trace it does not
* request storage (and the trace callback also does not request
* storage) then the basic block callback may still be called to
* translate for the trace.
*
* \sa #dr_register_bb_event()
*/
DR_EMIT_STORE_TRANSLATIONS = 0x01,
/**
* Only valid when applied to a basic block. Indicates that the
* block is eligible for persisting to a persistent code cache
* file on disk. By default, no blocks are eligible, as tools
* must take care in order to properly support persistence.
* Note that the block is not guaranteed to be persisted if
* it contains complex features that prevent DR from
* easily persisting it.
*/
DR_EMIT_PERSISTABLE = 0x02,
/**
* Only valid when applied to a basic block. Indicates that the
* block must terminate a trace. Normally this should be set when
* an abnormal exit is used from the block that is incompatible with
* trace building's attempt to inline the continuation from the block
* to its successor. Note that invoking dr_redirect_execution() from a
* clean call called from a block aborts trace building and thus this
* flag need not be set for that scenario.
*/
DR_EMIT_MUST_END_TRACE = 0x04,
/**
* Requests that DR relinquish control of the current thread and
* let it run natively until the client indicates that DR should
* take over again. While native, on Windows, currently only the
* thread init event (dr_register_thread_init_event()) will be
* raised, and nothing on Linux: no events will occur in the
* native thread. On Windows, DR tries to monitor any actions a
* native thread might take that affect correct execution from the
* code cache, but running natively carries risks. Consider this
* feature experimental, particularly on Linux.
*/
DR_EMIT_GO_NATIVE = 0x08,
} dr_emit_flags_t;
/* DR_API EXPORT END */
DR_API
/**
* Registers a callback function for the basic block event. DR calls
* \p func before inserting a new basic block into the code cache.
* When adding a basic block to a new trace, DR calls \p func again
* with \p for_trace set to true, giving the client the opportunity to
* keep its same instrumentation in the trace, or to change it. The
* original basic block's instrumentation is unchanged by whatever
* action is taken in the \p for_trace call.
*
* DR constructs <em>dynamic basic blocks</em>, which are distinct
* from a compiler's classic basic blocks. DR does not know all entry
* points ahead of time, and will end up duplicating the tail of a
* basic block if a later entry point is discovered that targets the
* middle of a block created earlier, or if a later entry point
* targets straight-line code that falls through into code already
* present in a block.
*
* DR may call \p func again if it needs to translate from code cache
* addresses back to application addresses, which happens on faulting
* instructions as well as in certain situations involving suspended
* threads or forcibly relocated threads. The \p translating
* parameter distinguishes the two types of calls and is further
* explained below.
*
* - \p drcontext is a pointer to the input program's machine context.
* Clients should not inspect or modify the context; it is provided as
* an opaque pointer (i.e., <tt>void *</tt>) to be passed to API
* routines that require access to this internal data.
* drcontext is specific to the current thread, but in normal
* configurations the basic block being created is thread-shared: thus,
* when allocating data structures with the same lifetime as the
* basic block, usually global heap (#dr_global_alloc()) is a better
* choice than heap tied to the thread that happened to first create
* the basic block (#dr_thread_alloc()). Thread-private heap is fine
* for temporary structures such as instr_t and instrlist_t.
*
* - \p tag is a unique identifier for the basic block fragment.
* Use dr_fragment_app_pc() to translate it to an application address.
* - \p bb is a pointer to the list of instructions that comprise the
* basic block. Clients can examine, manipulate, or completely
* replace the instructions in the list.
*
* - \p translating indicates whether this callback is for basic block
* creation (false) or is for address translation (true). This is
* further explained below.
*
* \return a #dr_emit_flags_t flag.
*
* The user is free to inspect and modify the block before it
* executes, but must adhere to the following restrictions:
* - If there is more than one application branch, only the last can be
* conditional.
* - An application conditional branch must be the final
* instruction in the block.
* - An application direct call must be the final
* instruction in the block unless it is inserted by DR for elision and the
* subsequent instructions are the callee.
* - There can only be one indirect branch (call, jump, or return) in
* a basic block, and it must be the final instruction in the
* block.
* - There can only be one far branch (call, jump, or return) in
* a basic block, and it must be the final instruction in the
* block.
* - The exit control-flow of a block ending in a system call or
* int instruction cannot be changed, nor can instructions be inserted
* after the system call or int instruction itself, unless
* the system call or int instruction is removed entirely.
* - The number of an interrupt cannot be changed. (Note that the
* parameter to a system call, normally kept in the eax register, can
* be freely changed in a basic block: but not in a trace.)
* - A system call or interrupt instruction can only be added
* if it satisfies the above constraints: i.e., if it is the final
* instruction in the block and the only system call or interrupt.
* - Any AArch64 #OP_isb instruction must be the last instruction
* in its block.
* - All IT blocks must be legal. For example, application instructions
* inside an IT block cannot be removed or added to without also
* updating the OP_it instruction itself. Clients can use
* the combination of dr_remove_it_instrs() and dr_insert_it_instrs()
* to more easily manage IT blocks while maintaining the simplicity
* of examining individual instructions in isolation.
* - The block's application source code (as indicated by the
* translation targets, set by #instr_set_translation()) must remain
* within the original bounds of the block (the one exception to this
* is that a jump can translate to its target). Otherwise, DR's cache
* consistency algorithms cannot guarantee to properly invalidate the
* block if the source application code is modified. To send control
* to other application code regions, truncate the block and use a
* direct jump to target the desired address, which will then
* materialize in the subsequent block, rather than embedding the
* desired instructions in this block.
* - There is a limit on the size of a basic block in the code cache.
* DR performs its own modifications, especially on memory writes for
* cache consistency of self-modifying (or false sharing) code
* regions. If an assert fires in debug build indicating a limit was
* reached, either truncate blocks or use the -max_bb_instrs runtime
* option to ask DR to make them smaller.
*
* To support transparent fault handling, DR must translate a fault in the
* code cache into a fault at the corresponding application address. DR
* must also be able to translate when a suspended thread is examined by
* the application or by DR itself for internal synchronization purposes.
* If the client is only adding observational instrumentation (i.e., meta
* instructions: see #instr_set_meta()) (which should not fault) and
* is not modifying, reordering, or removing application instructions,
* these details can be ignored. In that case the client should return
* #DR_EMIT_DEFAULT and set up its basic block callback to be deterministic
* and idempotent. If the client is performing modifications, then in
* order for DR to properly translate a code cache address the client must
* use #instr_set_translation() in the basic block creation callback to set
* the corresponding application address (the address that should be
* presented to the application as the faulting address, or the address
* that should be restarted after a suspend) for each modified instruction
* and each added application instruction (see #instr_set_app()).
*
* There are two methods for using the translated addresses:
*
* -# Return #DR_EMIT_STORE_TRANSLATIONS from the basic block creation
* callback. DR will then store the translation addresses and use
* the stored information on a fault. The basic block callback for
* \p tag will not be called with \p translating set to true. Note
* that unless #DR_EMIT_STORE_TRANSLATIONS is also returned for \p
* for_trace calls (or #DR_EMIT_STORE_TRANSLATIONS is returned in
* the trace callback), each constituent block comprising the trace
* will need to be re-created with both \p for_trace and \p
* translating set to true. Storing translations uses additional
* memory that can be significant: up to 20% in some cases, as it
* prevents DR from using its simple data structures and forces it
* to fall back to its complex, corner-case design. This is why DR
* does not store all translations by default.
* -# Return #DR_EMIT_DEFAULT from the basic block creation callback.
* DR will then call the callback again during fault translation
* with \p translating set to true. All modifications to \p bb
* that were performed on the creation callback must be repeated on
* the translating callback. This option is only possible when
* basic block modifications are deterministic and idempotent, but
* it saves memory. Naturally, global state changes triggered by
* block creation should be wrapped in checks for \p translating
* being false. Even in this case, #instr_set_translation() should
* be called for application instructions even when \p translating is
* false, as DR may decide to store the translations at creation
* time for reasons of its own.
*
* Furthermore, if the client's modifications change any part of the
* machine state besides the program counter, the client should use
* #dr_register_restore_state_event() or
* #dr_register_restore_state_ex_event() to restore the registers and
* application memory to their original application values.
*
* For meta instructions that do not reference application memory
* (i.e., they should not fault), leave the translation field as NULL.
* A NULL value instructs DR to use the subsequent application
* instruction's translation as the application address, and to fail
* when translating the full state. Since the full state will only be
* needed when relocating a thread (as stated, there will not be a
* fault here), failure indicates that this is not a valid relocation
* point, and DR's thread synchronization scheme will use another
* spot. If the translation field is set to a non-NULL value, the
* client should be willing to also restore the rest of the machine
* state at that point (restore spilled registers, etc.) via
* #dr_register_restore_state_event() or
* #dr_register_restore_state_ex_event(). This is necessary for meta
* instructions that reference application memory. DR takes care of
* such potentially-faulting instructions added by its own API
* routines (#dr_insert_clean_call() arguments that reference
* application data, #dr_insert_mbr_instrumentation()'s read of
* application indirect branch data, etc.)
*
* \note In order to present a more straightforward code stream to clients,
* this release of DR disables several internal optimizations. As a result,
* some applications may see a performance degradation. Applications making
* heavy use of system calls are the most likely to be affected.
* Future releases may allow clients some control over performance versus
* visibility. The \ref op_speed "-opt_speed" option can regain some
* of this performance at the cost of more complex basic blocks that
* cross control transfers.
*
* \note If multiple clients are present, the instruction list for a
* basic block passed to earlier-registered clients will contain the
* instrumentation and modifications put in place by later-registered
* clients.
*
* \note Basic blocks can be deleted due to hitting capacity limits or
* cache consistency events (when the source application code of a
* basic block is modified). In that case, the client will see a new
* basic block callback if the block is then executed again after
* deletion. The deletion event (#dr_register_delete_event()) will be
* raised at deletion time.
*
* \note If the -thread_private runtime option is specified, clients
* should expect to see duplicate tags for separate threads, albeit
* with different dcrcontext values. Additionally, DR employs a
* cache-sizing algorithm for thread private operation that
* proactively deletes fragments. Even with thread-shared caches
* enabled, however, certain situations cause DR to emit
* thread-private basic blocks (e.g., self-modifying code). In this
* case, clients should be prepared to see duplicate tags without an
* intermediate deletion.
*
* \note A client can change the control flow of the application by
* changing the control transfer instruction at end of the basic block.
* If a basic block is ended with a non-control transfer instruction,
* an application jump instruction can be inserted.
* If a basic block is ended with a conditional branch,
* \p instrlist_set_fall_through_target can be used to change the
* fall-through target.
* If a basic block is ended with a call instruction,
* \p instrlist_set_return_target can be used to change the return
* target of the call.
*/
void dr_register_bb_event(dr_emit_flags_t (*func)(void *drcontext, void *tag,
instrlist_t *bb, bool for_trace,
bool translating));
DR_API
/**
* Unregister a callback function for the basic block event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*
* \note We do not recommend unregistering for the basic block event
* unless it aways returned #DR_EMIT_STORE_TRANSLATIONS (including
* when \p for_trace is true, or if the client has a trace creation
* callback that returns #DR_EMIT_STORE_TRANSLATIONS). Unregistering
* can prevent proper state translation on a later fault or other
* translation event for this basic block or for a trace that includes
* this basic block. Instead of unregistering, turn the event
* callback into a nop.
*/
bool dr_unregister_bb_event(dr_emit_flags_t (*func)(void *drcontext, void *tag,
instrlist_t *bb, bool for_trace,
bool translating));
DR_API
/**
* Registers a callback function for the trace event. DR calls \p func
* before inserting a new trace into the code cache. DR may call \p func
* again if it needs to translate from code cache addresses back to
* application addresses, which happens on faulting instructions as well as
* in certain situations involving suspended threads or forcibly relocated
* threads. The \p translating parameter distinguishes the two types of
* calls and behaves identically to the same parameter in the basic
* block callback: see #dr_register_bb_event() for further details.
*
* Traces are not built if the -disable_traces runtime option
* is specified.
*
* - \p drcontext is a pointer to the input program's machine context.
* Clients should not inspect or modify the context; it is provided as
* an opaque pointer (i.e., <tt>void *</tt>) to be passed to API
* routines that require access to this internal data.
* - \p tag is a unique identifier for the trace fragment.
* - \p trace is a pointer to the list of instructions that comprise the
* trace.
* - \p translating indicates whether this callback is for trace creation
* (false) or is for fault address recreation (true). This is further
* explained below.
*
* \return a #dr_emit_flags_t flag.
*
* The user is free to inspect and modify the non-control-flow
* instructions in the trace before it
* executes, with certain restrictions
* that include those for basic blocks (see dr_register_bb_event()).
* Additional restrictions unique to traces also apply:
* - The sequence of blocks composing the trace cannot be changed once
* the trace is created. Instead, modify the component blocks by
* changing the block continuation addresses in the basic block callbacks
* (called with \p for_trace set to true) as the trace is being built.
* - The (application) control flow instruction (if any) terminating each
* component block cannot be changed.
* - Application control flow instructions cannot be added.
* - The parameter to a system call, normally kept in the eax register,
* cannot be changed.
* - A system call or interrupt instruction cannot be added.
* - If both a floating-point state save instruction (fnstenv, fnsave,
* fxsave, xsave, or xsaveopt) and a prior regular floating-point
* instruction are present, the regular instruction cannot be
* removed.
*
* If hitting a size limit due to extensive instrumentation, reduce
* the -max_trace_bbs option to start with a smaller trace.
*
* The basic block restrictions on modifying application source code
* apply to traces as well. If the user wishes to change which basic
* blocks comprise the trace, either the
* #dr_register_end_trace_event() should be used or the \p for_trace
* basic block callbacks should modify their continuation addresses
* via direct jumps.
*
* All of the comments for #dr_register_bb_event() regarding
* transparent fault handling and state translation apply to the trace
* callback as well. Please read those comments carefully.
*
* \note As each basic block is added to a new trace, the basic block
* callback (see #dr_register_bb_event()) is called with its \p
* for_trace parameter set to true. In order to preserve basic block
* instrumentation inside of traces, a client need only act
* identically with respect to the \p for_trace parameter; it can
* ignore the trace event if its goal is to place instrumentation
* on all code.
*
* \note Certain control flow modifications applied to a basic block
* can prevent it from becoming part of a trace: e.g., adding
* additional application control transfers.
*
* \note If multiple clients are present, the instruction list for a
* trace passed to earlier-registered clients will contain the
* instrumentation and modifications put in place by later-registered
* clients; similarly for each constituent basic block.
*
* \note Traces can be deleted due to hitting capacity limits or cache
* consistency events (when the source application code of a trace is
* modified). In that case, the client will see a new trace callback
* if a new trace containing that code is created again after
* deletion. The deletion event (#dr_register_delete_event()) will be
* raised at deletion time.
*/
void dr_register_trace_event(dr_emit_flags_t (*func)(void *drcontext, void *tag,
instrlist_t *trace,
bool translating));
DR_API
/**
* Unregister a callback function for the trace event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*
* \note We do not recommend unregistering for the trace event unless it
* always returned #DR_EMIT_STORE_TRANSLATIONS, as doing so can prevent
* proper state translation on a later fault or other translation event.
* Instead of unregistering, turn the event callback into a nop.
*/
bool dr_unregister_trace_event(dr_emit_flags_t (*func)(void *drcontext, void *tag,
instrlist_t *trace,
bool translating));
# ifdef CUSTOM_TRACES
/* DR_API EXPORT BEGIN */
/**
* DR will call the end trace event if it is registered prior to
* adding each basic block to a trace being generated. The return
* value of the event callback should be from the
* dr_custom_trace_action_t enum.
*
* \note DR treats CUSTOM_TRACE_CONTINUE as an advisement only. Certain
* fragments are not suitable to be included in a trace and if DR runs
* into one it will end the trace regardless of what the client returns
* through the event callback.
*/
typedef enum {
CUSTOM_TRACE_DR_DECIDES,
CUSTOM_TRACE_END_NOW,
CUSTOM_TRACE_CONTINUE
} dr_custom_trace_action_t;
/* DR_API EXPORT END */
DR_API
/**
* Registers a callback function for the end-trace event. DR calls \p
* func before extending a trace with a new basic block. The \p func
* should return one of the #dr_custom_trace_action_t enum values.
*/
void dr_register_end_trace_event(dr_custom_trace_action_t (*func)(void *drcontext,
void *tag,
void *next_tag));
DR_API
/**
* Unregister a callback function for the end-trace event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool dr_unregister_end_trace_event(dr_custom_trace_action_t (*func)(void *drcontext,
void *tag,
void *next_tag));
# endif
/* For the new-bb-before-deletion-event problem (PR 495787, and
* described in the comment below):
* Note that we do not want a new "unreachable event" b/c clients need
* to keep bb info around in case the semi-flushed bb hits a fault.
* The main worry w/ the counter approach, in addition to ensuring
* it handles duplicates due to thread-private, is that can we
* guarantee that deletion events will be in order, or can a new
* fragment be deleted prior to older fragments? For most clients
* it won't matter I suppose.
*/
DR_API
/**
* Registers a callback function for the fragment deletion event. DR
* calls \p func whenever it removes a fragment from the code cache.
* Due to DR's high-performance non-precise flushing, a fragment
* can be made inaccessible but not actually freed for some time.
* A new fragment can thus be created before the deletion event
* for the old fragment is raised. We recommended using a counter
* to ignore subsequent deletion events when using per-fragment
* data structures and duplicate fragments are seen.
*
* \note drcontext may be NULL when thread-shared fragments are being
* deleted during process exit. For this reason, thread-private
* heap should not be used for data structures intended to be freed
* at thread-shared fragment deletion.
*/
void
dr_register_delete_event(void (*func)(void *drcontext, void *tag));
DR_API
/**
* Unregister a callback function for the fragment deletion event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
dr_unregister_delete_event(void (*func)(void *drcontext, void *tag));
DR_API
/**
* Registers a callback function for the machine state restoration event.
* DR calls \p func whenever it needs to translate a code cache machine
* context from the code cache to its corresponding original application
* context. DR needs to translate when instructions fault in the cache as
* well as when a suspended thread is examined or relocated for internal
* purposes.
*
* If a client is only adding instrumentation (meta-code: see
* #instr_is_meta()) that does not reference application memory,
* and is not reordering or removing application instructions, then it
* need not register for this event. If, however, a client is
* modifying application code or is adding code that can fault, the
* client must be capable of restoring the original context.
*
* When DR needs to translate a code cache context, DR recreates the
* faulting instruction's containing fragment, storing translation
* information along the way, by calling the basic block and/or trace event
* callbacks with the \p translating parameter set to true. DR uses the
* recreated code to identify the application instruction (\p mcontext.pc)
* corresponding to the faulting code cache instruction. If the client
* asked to store translation information by returning
* #DR_EMIT_STORE_TRANSLATIONS from the basic block or trace event
* callback, then this step of re-calling the event callback is skipped and
* the stored value is used as the application address (\p mcontext.pc).
*
* DR then calls the fault state restoration event to allow the client
* to restore the registers and application memory to their proper
* values as they would have appeared if the original application code
* had been executed up to the \p mcontext.pc instruction. Memory
* should only be restored if the \p restore_memory parameter is true;
* if it is false, DR may only be querying for the address (\p
* mcontext.pc) or register state and may not relocate this thread.
*
* DR will call this event for all translation attempts, even when the
* register state already contains application values, to allow
* clients to restore memory.
*
* The \p app_code_consistent parameter indicates whether the original
* application code containing the instruction being translated is
* guaranteed to still be in the same state it was when the code was
* placed in the code cache. This guarantee varies depending on the
* type of cache consistency being used by DR.
*
* The client can update \p mcontext.pc in this callback. The client
* should not change \p mcontext.flags: it should remain DR_MC_ALL.
*
* \note The passed-in \p drcontext may correspond to a different thread
* than the thread executing the callback. Do not assume that the
* executing thread is the target thread.
*/
void
dr_register_restore_state_event(void (*func)(void *drcontext, void *tag,
dr_mcontext_t *mcontext, bool restore_memory,
bool app_code_consistent));
DR_API
/**
* Unregister a callback function for the machine state restoration event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
dr_unregister_restore_state_event(void (*func)(void *drcontext, void *tag,
dr_mcontext_t *mcontext,
bool restore_memory,
bool app_code_consistent));
/* DR_API EXPORT BEGIN */
/**
* Data structure passed within dr_exception_t, dr_siginfo_t, and
* dr_restore_state_info_t.
* Contains information about the code fragment inside the code cache
* at the exception/signal/translation interruption point.
*/
typedef struct _dr_fault_fragment_info_t {
/**
* The tag of the code fragment inside the code cache at the
* exception/signal/translation interruption point. NULL for
* interruption not in the code cache.
*/
void *tag;
/**
* The start address of the code fragment inside the code cache at
* the exception/signal/translation interruption point. NULL for interruption
* not in the code cache. Clients are cautioned when examining
* code cache instructions to not rely on any details of code
* inserted other than their own.
*/
byte *cache_start_pc;
/** Indicates whether the interrupted code fragment is a trace */
bool is_trace;
/**
* Indicates whether the original application code containing the
* code corresponding to the exception/signal/translation interruption point
* is guaranteed to still be in the same state it was when the
* code was placed in the code cache. This guarantee varies
* depending on the type of cache consistency being used by DR.
*/
bool app_code_consistent;
} dr_fault_fragment_info_t;
/**
* Data structure passed to a restore_state_ex event handler (see
* dr_register_restore_state_ex_event()). Contains the machine
* context at the translation point and other translation
* information.
*/
typedef struct _dr_restore_state_info_t {
/**
* The application machine state at the translation point.
* The client can update register values and the program counter
* by changing this context. The client should not change \p
* mcontext.flags: it should remain DR_MC_ALL.
*/
dr_mcontext_t *mcontext;
/** Whether raw_mcontext is valid. */
bool raw_mcontext_valid;
/**
* The raw pre-translated machine state at the translation
* interruption point inside the code cache. Clients are
* cautioned when examining code cache instructions to not rely on
* any details of code inserted other than their own.
* Modifying this context will not affect the translation.
*/
dr_mcontext_t *raw_mcontext;
/**
* Information about the code fragment inside the code cache
* at the translation interruption point.
*/
dr_fault_fragment_info_t fragment_info;
} dr_restore_state_info_t;
/* DR_API EXPORT END */
DR_API
/**
* Registers a callback function for the machine state restoration
* event with extended information.
*
* This event is identical to that for dr_register_restore_state_event()
* with the following exceptions:
*
* - Additional information is provided in the
* dr_restore_state_info_t structure, including the pre-translation
* context (containing the address inside the code cache of the
* translation point) and the starting address of the containing
* fragment in the code cache. Certain registers may not contain
* proper application values in \p info->raw_mcontext. Clients are
* cautioned against relying on any details of code cache layout or
* register usage beyond instrumentation inserted by the client
* itself when examining \p info->raw_mcontext.
*
* - The callback function returns a boolean indicating the success of
* the translation. When DR is translating not for a fault but for
* thread relocation, the \p restore_memory parameter will be false.
* Such translation can target a meta-instruction that can fault
* (i.e., it has a non-NULL translation field). For that scenario, a client
* can choose not to translate. Such instructions do not always
* require full translation for faults, and allowing translation
* failure removes the requirement that a client must translate at
* all such instructions. Note, however, that returning false can
* cause performance degradation as DR must then resume the thread
* and attempt to re-suspend it at a safer spot. Clients must
* return true for translation points in application code in order
* to avoid catastropic failure to suspend, and should thus identify
* whether translation points are inside their own instrumentation
* before returning false. Translation for relocation will never
* occur in meta instructions, so clients only need to look for
* meta-may-fault instructions. Clients should never return false
* when \p restore_memory is true.
*
* - If multiple callbacks are registered, the first one that returns
* false will short-circuit event delivery to later callbacks.
*/
void
dr_register_restore_state_ex_event(bool (*func)(void *drcontext, bool restore_memory,
dr_restore_state_info_t *info));
DR_API
/**
* Unregister a callback function for the machine state restoration
* event with extended ifnormation. \return true if unregistration is
* successful and false if it is not (e.g., \p func was not
* registered).
*/
bool
dr_unregister_restore_state_ex_event(bool (*func)(void *drcontext, bool restore_memory,
dr_restore_state_info_t *info));
DR_API
/**
* Registers a callback function for the thread initialization event.
* DR calls \p func whenever the application creates a new thread.
*/
void
dr_register_thread_init_event(void (*func)(void *drcontext));
DR_API
/**
* Unregister a callback function for the thread initialization event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
dr_unregister_thread_init_event(void (*func)(void *drcontext));
DR_API
/**
* Registers a callback function for the thread exit event. DR calls
* \p func whenever an application thread exits. The passed-in
* drcontext should be used instead of calling
* dr_get_current_drcontext(), as the thread exit event may be invoked
* from other threads, and using dr_get_current_drcontext() can result
* in failure to clean up the right resources, and at process exit
* time it may return NULL.
*
* On Linux, SYS_execve may or may not result in a thread exit event.
* If the client registers its thread exit callback as a pre-SYS_execve
* callback as well, it must ensure that the callback acts as noop
* if called for the second time.
*
* On Linux, the thread exit event may be invoked twice for the same thread
* if that thread is alive during a process fork, but doesn't call the fork
* itself. The first time the event callback is executed from the fork child
* immediately after the fork, the second time it is executed during the
* regular thread exit.
* Clients may want to avoid touching resources shared between processes,
* like files, from the post-fork execution of the callback. The post-fork
* version of the callback can be recognized by dr_get_process_id()
* returning a different value than dr_get_process_id_from_drcontext().
*
* See dr_set_process_exit_behavior() for options controlling performance
* and whether thread exit events are invoked at process exit time in
* release build.
*/
void
dr_register_thread_exit_event(void (*func)(void *drcontext));
DR_API
/**
* Unregister a callback function for the thread exit event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
dr_unregister_thread_exit_event(void (*func)(void *drcontext));
/* DR_API EXPORT TOFILE dr_events.h */
/* DR_API EXPORT BEGIN */
/**
* Flags controlling thread behavior at process exit time in release build.
* See dr_set_process_exit_behavior() for further details.
*/
typedef enum {
/**
* Do not guarantee that the process exit event is executed
* single-threaded. This is equivalent to specifying the \p
* -multi_thread_exit runtime option. Setting this flag can improve
* process exit performance, but usually only when the
* #DR_EXIT_SKIP_THREAD_EXIT flag is also set, or when no thread exit
* events are registered.
*/
DR_EXIT_MULTI_THREAD = 0x01,
/**
* Do not invoke thread exit event callbacks at process exit time.
* Thread exit event callbacks will still be invoked at other times.
* This is equivalent to setting the \p -skip_thread_exit_at_exit
* runtime option. Setting this flag can improve process exit
* performance, but usually only when the #DR_EXIT_MULTI_THREAD flag is
* also set, or when no process exit event is registered.
*/
DR_EXIT_SKIP_THREAD_EXIT = 0x02,
} dr_exit_flags_t;
/* DR_API EXPORT END */
DR_API
/**
* Specifies how process exit should be handled with respect to thread exit
* events and thread synchronization in release build. In debug build, and
* in release build by default, all threads are always synchronized at exit
* time, resulting in a single-threaded process exit event, and all thread
* exit event callbacks are always called. This routine can provide more
* performant exits in release build by avoiding the synchronization if the
* client is willing to skip thread exit events at process exit and is
* willing to execute its process exit event with multiple live threads.
*/
void
dr_set_process_exit_behavior(dr_exit_flags_t flags);
DR_API
/**
* The #DR_DISALLOW_UNSAFE_STATIC declaration requests that DR perform sanity
* checks to ensure that client libraries will also operate safely when linked
* statically into an application. This overrides that request, facilitating
* having runtime options that are not supported in a static context.
*/
void
dr_allow_unsafe_static_behavior(void);
# ifdef UNIX
DR_API
/**
* Registers a callback function for the fork event. DR calls \p func
* whenever the application forks a new process.
* \note Valid on Linux only.
*/
void
dr_register_fork_init_event(void (*func)(void *drcontext));
DR_API
/**
* Unregister a callback function for the fork event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
dr_unregister_fork_init_event(void (*func)(void *drcontext));
# endif
DR_API
/**
* Registers a callback function for the module load event. DR calls
* \p func whenever the application loads a module (typically a
* library but this term includes the executable). The \p loaded
* parameter indicates whether the module is fully initialized by the
* loader or in the process of being loaded. This parameter is present
* only for backward compatibility: current versions of DR always pass true,
* and the client can assume that relocating, rebinding, and (on Linux) segment
* remapping have already occurred.
*
* \note The module_data_t \p info passed to the callback routine is
* valid only for the duration of the callback and should not be
* freed; a persistent copy can be made with dr_copy_module_data().
*
* \note Registration cannot be done during the basic block event: it should be
* done at initialization time.
*/
void
dr_register_module_load_event(void (*func)(void *drcontext, const module_data_t *info,
bool loaded));
DR_API
/**
* Unregister a callback for the module load event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*
* \note Unregistering for this event is not supported during the
* basic block event.
*/
bool
dr_unregister_module_load_event(void (*func)(void *drcontext, const module_data_t *info,
bool loaded));
DR_API
/**
* Registers a callback function for the module unload event. DR
* calls \p func whenever the application unloads a module.
* \note The module_data_t \p *info passed to
* the callback routine is valid only for the duration of the callback
* and should not be freed; a persistent copy can be made with
* dr_copy_module_data().
*/
void
dr_register_module_unload_event(void (*func)(void *drcontext, const module_data_t *info));
DR_API
/**
* Unregister a callback function for the module unload event.
* \return true if unregistration is successful and false if it is not
* (e.g., \p func was not registered).
*/
bool
dr_unregister_module_unload_event(void (*func)(void *drcontext,
const module_data_t *info));
/* DR_API EXPORT BEGIN */
/** Identifies the type of kernel transfer for dr_register_kernel_xfer_event(). */
typedef enum {
DR_XFER_SIGNAL_DELIVERY, /**< Signal delivery to application handler. */
DR_XFER_SIGNAL_RETURN, /**< Signal return system call. */
DR_XFER_APC_DISPATCHER, /**< Asynchronous procedure call dispatcher. */
DR_XFER_EXCEPTION_DISPATCHER, /**< Exception dispatcher. */
DR_XFER_RAISE_DISPATCHER, /**< Raised exception dispatcher. */
DR_XFER_CALLBACK_DISPATCHER, /**< Callback dispatcher. */
DR_XFER_CALLBACK_RETURN, /**< A return from a callback by syscall or interrupt. */
DR_XFER_CONTINUE, /**< NtContinue system call. */
DR_XFER_SET_CONTEXT_THREAD, /**< NtSetContextThread system call. */
DR_XFER_CLIENT_REDIRECT, /**< dr_redirect_execution() or #DR_SIGNAL_REDIRECT. */
DR_XFER_RSEQ_ABORT, /**< A Linux restartable sequence was aborted. */
} dr_kernel_xfer_type_t;
/** Data structure passed for dr_register_kernel_xfer_event(). */
typedef struct _dr_kernel_xfer_info_t {
/** The type of event. */
dr_kernel_xfer_type_t type;
/**
* The source machine context which is about to be changed. This may be NULL
* if it is unknown, which is the case for #DR_XFER_CALLBACK_DISPATCHER and
* #DR_XFER_RSEQ_ABORT (where the PC is not known but the rest of the state
* matches the current state).
*/
const dr_mcontext_t *source_mcontext;
/**
* The target program counter of the transfer. To obtain the full target state,
* call dr_get_mcontext(). (For efficiency purposes, only frequently needed
* state is included by default.)
*/
app_pc target_pc;
/**
* The target stack pointer of the transfer. To obtain the full target state,
* call dr_get_mcontext(). (For efficiency purposes, only frequently needed
* state is included by default.)
*/
reg_t target_xsp;
/** For #DR_XFER_SIGNAL_DELIVERY and #DR_XFER_SIGNAL_RETURN, the signal number. */
int sig;
} dr_kernel_xfer_info_t;
/* DR_API EXPORT END */
DR_API
/**
* Registers a callback function for the kernel transfer event. DR
* calls \p func whenever the kernel is about to directly transfer control
* without an explicit user-mode control transfer instruction.
* This includes the following scenarios, which are distinguished by \p type:
* - On UNIX, a signal is about to be delivered to an application handler.
* This event differs from a dr_register_signal_event() callback in that the
* latter is called regardless of whether the application has a handler,
* and it does not provide the target context of any handler.
* - On UNIX, a signal return system call is about to be invoked.