/
globals.h
1127 lines (1000 loc) · 40.9 KB
/
globals.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) 2011-2017 Google, Inc. All rights reserved.
* Copyright (c) 2000-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) 2001-2003 Massachusetts Institute of Technology */
/* Copyright (c) 2000-2001 Hewlett-Packard Company */
/*
* globals.h - global defines and typedefs, included in all files
*/
#ifndef _GLOBALS_H_
#define _GLOBALS_H_ 1
#include "configure.h"
#ifdef WINDOWS
/* Vista SDK compiler default is to set NTDDI_VERSION to NTDDI_LONGHORN, causing
* problems w/ new Vista-only flags like in PROCESS_ALL_ACCESS in win32/injector.c.
* The problematic flag there, PROCESS_QUERY_LIMITED_INFORMATION, is a subset of
* PROCESS_QUERY_INFORMATION, so we don't lose anything by not asking for it on Vista.
* But if they add new non-subset flags in the future we'd need dynamic dispatch,
* as earlier Windows versions give access denied on unknown flags!
*/
#define _WIN32_WINNT _WIN32_WINNT_NT4 /* ==0x0400; NTDDI_VERSION is set from this */
# define WIN32_LEAN_AND_MEAN
/* Exclude rarely-used stuff from Windows headers */
/* XXX Case 1167: work in progress: bumping up warning level to 4 */
#pragma warning( disable : 4054) // from function pointer to data pointer
#pragma warning( disable : 4100) // 'envp' : unreferenced formal parameter
#pragma warning( disable : 4127) // conditional expr is constant (majority of warnings)
#pragma warning( disable : 4189) // local variable is initialized but not referenced
#pragma warning( disable : 4204) // nonstd extension: non-constant aggregate initializer
#pragma warning( disable : 4210) // nonstd extension: function given file scope
#pragma warning( disable : 4505) // unreferenced local function has been removed
#pragma warning( disable : 4702) // unreachable code (DEBUG=0, for INTERNAL_OPTION test)
#pragma warning( disable : 4324) // structure was padded due to __declspec(align())
#pragma warning( disable : 4709) // comma operator within array index expression
#pragma warning( disable : 4214) // nonstd extension: bit field types other than int
/**************************************************/
/* warnings on compiling with VC 8.0, all on VC or PlatformSDK header files */
/* shows up in buildtools/VC/8.0/dist/VC/include/vadefs.h
* supposed to include identifier in the pop pragma and they don't
*/
#pragma warning( disable : 4159) // #pragma pack has popped previously pushed identifier
/* FIXME case 191729: this is coming from our own code. We could
* switch to the _s versions when on Windows.
*/
#pragma warning( disable : 4996) //'sscanf' was declared deprecated
/**************************************************/
#endif
#include "globals_shared.h"
/* currently we always export statistics structure */
#define DYNAMORIO_STATS_EXPORTS 1
/* we only export IR interface if CLIENT_INTERFACE is defined */
#ifdef CLIENT_INTERFACE
/* in Makefile, we define these (so that genapi.pl, etc. get them):
* define DYNAMORIO_IR_EXPORTS 1
* define CUSTOM_EXIT_STUBS 1
* define CUSTOM_TRACES 1
* CUSTOM_TRACES_RET_REMOVAL is aggressive -- assumes calling convention kept
* Only useful if custom traces are doing inlining => do not define for external
* release, or even by default for internal since it's always on even if
* not building custom traces!
*/
#endif /* CLIENT_INTERFACE */
# ifdef WINDOWS
# define DYNAMORIO_EXPORT __declspec(dllexport)
# elif defined(USE_VISIBILITY_ATTRIBUTES)
/* PR 262804: we use "protected" instead of "default" to ensure our
* own uses won't be preempted. Note that for DR_APP_API in
* lib/dr_app.h we get a link error trying to use "protected": but we
* don't use dr_app_* internally anyway, so leaving as default.
*/
# define DYNAMORIO_EXPORT __attribute__ ((visibility ("protected")))
# else
/* visibility attribute not available in gcc < 3.3 (we use linker script) */
# define DYNAMORIO_EXPORT
# endif
#ifdef DYNAMORIO_IR_EXPORTS
# define DR_API DYNAMORIO_EXPORT
#else
# define DR_API
#endif
#ifdef UNSUPPORTED_API
# define DR_UNS_API DR_API
#else
# define DR_UNS_API /* nothing */
#endif
#ifdef WINDOWS
# define NOINLINE __declspec(noinline)
#else
# define NOINLINE __attribute__((noinline))
#endif
#define INLINE_ONCE inline
#include <stdlib.h>
#include <stdio.h>
/* N.B.: some of these typedefs and defines are duplicated in
* lib/globals_shared.h!
*/
#ifdef WINDOWS
#include <windows.h>
typedef unsigned long ulong;
typedef unsigned short ushort;
/* We can't put this in globals_shared.h b/c it needs windows.h and
* not all users of globals_shared.h want that included, so we
* duplicate it here (we do have Linux file_t stuff in globals_shared.h)
*/
/* since a FILE cannot be used outside of the DLL it was created in,
* we have to use HANDLE on Windows
* we hide the distinction behind the file_t type
*/
typedef HANDLE file_t;
#define INVALID_FILE INVALID_HANDLE_VALUE
#define STDOUT (file_t)get_stdout_handle()
#define STDERR (file_t)get_stderr_handle()
#define STDIN (file_t)get_stdin_handle()
#define DIRSEP '\\'
#define ALT_DIRSEP '/'
#else /* UNIX */
/* uint, ushort, and ulong are in types.h */
# if defined(MACOS) || defined(ANDROID)
typedef unsigned long ulong;
# endif
#include <sys/types.h> /* for wait */
#define DIRSEP '/'
#define ALT_DIRSEP DIRSEP
#endif
/* FIXME: what is range of thread_id_t on linux and on win32?
* linux routines use -1 as sentinel, right?
* on win32, are ids only 16 bits?
* if so, change thread_id_t to be a signed int and use -1?
* For now, based on observation, no process on linux and no thread on windows
* has id 0 (on windows even a new thread in its init apc has a non-0 id)
*/
#define INVALID_THREAD_ID 0
typedef unsigned char uchar;
typedef byte * cache_pc; /* fragment cache pc */
#define SUCCESS 0
#define FAILURE 1
/* macros to make conditional compilation look prettier */
#ifdef DGC_DIAGNOSTICS
# define _IF_DGCDIAG(x) , x
# define IF_DGCDIAG_ELSE(x, y) x
#else
# define _IF_DGCDIAG(x)
# define IF_DGCDIAG_ELSE(x, y) y
#endif
/* make sure defines are consistent */
#if !defined(X86) && !defined(ARM) && !defined(AARCH64)
# error Must define X86, ARM or AARCH64: no other platforms are supported
#endif
#if defined(PAPI) && defined(WINDOWS)
# error PAPI does not work on WINDOWS
#endif
#if defined(DCONTEXT_IN_EDI) && !defined(STEAL_REGISTER)
# error Must steal register to keep dcontext in edi
#endif
#ifdef DGC_DIAGNOSTICS
# ifndef PROGRAM_SHEPHERDING
# error DGC_DIAGNOSTICS requires PROGRAM_SHEPHERDING
# endif
# ifndef DEBUG
# error DGC_DIAGNOSTICS requires DEBUG
# endif
#endif
#ifndef PROGRAM_SHEPHERDING
# ifdef SIMULATE_ATTACK
# error SIMULATE_ATTACK requires PROGRAM_SHEPHERDING
# endif
#endif
/* in buildmark.c */
extern const char dynamorio_version_string[];
extern const char dynamorio_buildmark[];
struct _opnd_t;
typedef struct _opnd_t opnd_t;
struct _instr_t;
typedef struct _instr_t instr_t;
struct _instr_list_t;
struct _fragment_t;
typedef struct _fragment_t fragment_t;
struct _future_fragment_t;
typedef struct _future_fragment_t future_fragment_t;
struct _trace_t;
typedef struct _trace_t trace_t;
struct _linkstub_t;
typedef struct _linkstub_t linkstub_t;
struct _dcontext_t;
typedef struct _dcontext_t dcontext_t;
struct vm_area_vector_t;
typedef struct vm_area_vector_t vm_area_vector_t;
struct _coarse_info_t;
typedef struct _coarse_info_t coarse_info_t;
struct _coarse_freeze_info_t;
typedef struct _coarse_freeze_info_t coarse_freeze_info_t;
struct _module_data_t;
/* DR_API EXPORT TOFILE dr_defines.h */
/* DR_API EXPORT BEGIN */
typedef struct _instr_list_t instrlist_t;
typedef struct _module_data_t module_data_t;
/* DR_API EXPORT END */
/* DR_API EXPORT BEGIN */
#ifdef X64
/**
* Upper note values are reserved for core DR.
*/
# define DR_NOTE_FIRST_RESERVED 0xfffffffffffffff0ULL
#else
/**
* Upper note values are reserved for core DR.
*/
# define DR_NOTE_FIRST_RESERVED 0xfffffff0UL
#endif
#define DR_NOTE_ANNOTATION (DR_NOTE_FIRST_RESERVED + 1)
/**
* Structure written by dr_get_time() to specify the current time.
*/
typedef struct {
uint year; /**< The current year. */
uint month; /**< The current month, in the range 1 to 12. */
uint day_of_week; /**< The day of the week, in the range 0 to 6. */
uint day; /**< The day of the month, in the range 1 to 31. */
uint hour; /**< The hour of the day, in the range 0 to 23. */
uint minute; /**< The minutes past the hour. */
uint second; /**< The seconds past the minute. */
uint milliseconds; /**< The milliseconds past the second. */
} dr_time_t;
/* DR_API EXPORT END */
#if defined(RETURN_AFTER_CALL) || defined(RCT_IND_BRANCH)
struct _rct_module_table_t;
typedef struct _rct_module_table_t rct_module_table_t;
typedef enum {
RCT_RAC = 0,
RCT_RCT,
RCT_NUM_TYPES,
} rct_type_t;
#endif
typedef struct _thread_record_t {
thread_id_t id; /* thread id */
#ifdef WINDOWS
HANDLE handle; /* win32 thread handle */
bool retakeover;
#else
process_id_t pid; /* thread group id */
bool execve; /* exiting due to execve (i#237/PR 498284) */
#endif
uint num; /* creation ordinal */
bool under_dynamo_control; /* used for deciding whether to intercept events */
dcontext_t *dcontext; /* allows other threads to see this thread's context */
struct _thread_record_t * next;
} thread_record_t;
/* we don't include dr_api.h, that's for external use, we only need _app
* (everything in dr_defines.h is duplicated in our own header files)
*/
#ifdef DR_APP_EXPORTS
/* we only export app interface if DR_APP_EXPORTS is defined */
# include "dr_app.h"
/* a few always-exported routines are part of the app interface */
# undef DYNAMORIO_EXPORT
# define DYNAMORIO_EXPORT DR_APP_API
#endif
#include "heap.h"
#include "utils.h"
#include "options.h"
#include "os_exports.h"
#include "arch_exports.h"
#include "dr_helper.h"
#include "vmareas.h"
#include "instrlist.h"
#include "dispatch.h"
#include "dr_stats.h"
#ifdef CLIENT_INTERFACE
/* did the client request a premature exit at a potentially awkward spot
* (nudge handler, signal handler)?
*/
extern bool client_requested_exit;
typedef struct _client_to_do_list_t {
/* used to make a list of fragments to delete/replace */
/* deletes frag at tag if ilist is null else replaces it with ilist */
instrlist_t *ilist;
app_pc tag;
struct _client_to_do_list_t *next;
} client_todo_list_t;
/* Clients need a separate list to queue up flush requests from dr_flush() */
typedef struct _client_flush_req_t {
app_pc start;
size_t size;
uint flush_id; /* client supplied identifier for this flush */
void (*flush_callback)(int);
struct _client_flush_req_t *next;
} client_flush_req_t;
/* for -thin_client we don't allocate client_data currently, also client_data could be
* NULL during thread startup or teardown (i.e. mutex_wait_contended_lock() usage) */
#define IS_CLIENT_THREAD(dcontext) \
((dcontext) != NULL && dcontext != GLOBAL_DCONTEXT && \
(dcontext)->client_data != NULL && (dcontext)->client_data->is_client_thread)
#ifdef DEBUG
/* For use after dcontext->client_data is NULL */
# define IS_CLIENT_THREAD_EXITING(dcontext) \
((dcontext) != NULL && dcontext != GLOBAL_DCONTEXT && \
(dcontext)->is_client_thread_exiting)
#endif
/* Client interface-specific data for dcontexts */
typedef struct _client_data_t {
/* field for use by user via exported API */
void * user_field;
client_todo_list_t * to_do;
client_flush_req_t *flush_list;
# ifdef CLIENT_SIDELINE
mutex_t sideline_mutex;
# endif
/* fields for doing release and debug build checks against erroneous API usage */
module_data_t *no_delete_mod_data;
/* Client-owned threads, such as a client nudge thread, require special
* synchronization support. is_client_thread means that the thread is currently
* completely owned by the client. client_thread_safe_for_sync is use to mark
* client-owned threads that are safe for synch_with_all_threads synchronization but
* are in dynamo/native code (such as in dr_thread_yield(), dr_sleep(),
* dr_mutex_lock() and dr_messagebox()). Note it does not need to be set when
* the client is in client library code. For dr_mutex_lock() we set client_grab_mutex
* to the client mutex that is being locked so that we can set
* client_thread_safe_for_sync only around the actual wait.
* FIXME - PR 231301, we may need a way for clients that call ntdll directly to
* mark client_thread_safe_for_synch for client-owned threads when calling out to
* ntdll. Especially if they're calling system calls that wait or take a long time
* to finish etc. Applies to generated code and other libraries called by the client
* lib as well.
*/
bool is_client_thread; /* NOTE - use IS_CLIENT_THREAD() */
bool client_thread_safe_for_synch;
/* i#1420: we add a field to indicate if we are in a safe syscall spot
* for THREAD_SYNCH_TERMINATED_AND_CLEANED.
*/
bool at_safe_to_terminate_syscall;
bool suspendable; /* suspend w/ synchall: PR 609569 */
bool left_unsuspended; /* not suspended by synchall: PR 609569 */
uint mutex_count; /* mutex nesting: for PR 558463 */
void *client_grab_mutex;
# ifdef DEBUG
bool is_translating;
# endif
/* flags for asserts on linux and for getting param base right on windows */
bool in_pre_syscall;
bool in_post_syscall;
/* flag for dr_syscall_invoke_another() */
bool invoke_another_syscall;
/* flags for dr_get_mcontext (i#117/PR 395156) */
bool mcontext_in_dcontext;
bool suspended;
/* 2 other ways to point at a context for dr_{g,s}et_mcontext() */
priv_mcontext_t *cur_mc;
os_cxt_ptr_t os_cxt;
} client_data_t;
#else
# define IS_CLIENT_THREAD(dcontext) false
#endif /* CLIENT_INTERFACE */
#ifdef UNIX
/* i#61/PR 211530: nudges on Linux do not use separate threads */
typedef struct _pending_nudge_t {
nudge_arg_t arg;
struct _pending_nudge_t *next;
} pending_nudge_t;
#endif
/* size of each Dynamo thread-private stack */
#define DYNAMORIO_STACK_SIZE dynamo_options.stack_size
/* global flags */
extern bool automatic_startup; /* ignore start/stop api, run entire program */
extern bool control_all_threads; /* ok for "weird" things to happen -- not all
threads are under our control */
extern bool dynamo_heap_initialized; /* has dynamo_heap been initialized? */
extern bool dynamo_initialized; /* has dynamo been initialized? */
extern bool dynamo_exited; /* has dynamo exited? */
extern bool dynamo_exited_all_other_threads; /* has dynamo exited and synched? */
extern bool dynamo_exited_and_cleaned; /* has dynamo component cleanup started? */
#ifdef DEBUG
extern bool dynamo_exited_log_and_stats; /* are stats and logfile shut down? */
#endif
extern bool dynamo_resetting; /* in middle of global reset? */
extern bool dynamo_all_threads_synched; /* are all other threads suspended safely? */
/* Not guarded by DR_APP_EXPORTS because later detach implementations might not
* go through the app interface.
*/
extern bool doing_detach;
#if defined(CLIENT_INTERFACE) || defined(STANDALONE_UNIT_TEST)
extern bool standalone_library; /* used as standalone library */
#else
/* avoid complex ifdefs everywhere */
# define standalone_library false
#endif
#ifdef UNIX
extern bool post_execve; /* have we performed an execve? */
/* i#237/PR 498284: vfork threads that execve need to be separately delay-freed */
extern int num_execve_threads;
#endif
/* global instance of statistics struct */
extern dr_statistics_t *stats;
/* the process-wide logfile */
extern file_t main_logfile;
/* initial stack so we don't have to use app's */
extern byte * initstack;
extern mutex_t initstack_mutex;
extern byte * initstack_app_xsp;
#ifdef WINDOWS
/* PR203701: separate stack for error reporting when the dstack is exhausted */
extern byte * exception_stack;
#endif
/* keeps track of how many threads are in cleanup_and_terminate so that we know
* if any threads could still be using shared resources even if they aren't on
* the all_threads list */
extern volatile int exiting_thread_count;
/* Tracks newly created threads not yet on the all_threads list. */
extern volatile int uninit_thread_count;
/* Called before a second thread is ever scheduled. */
void pre_second_thread(void);
bool is_on_initstack(byte *esp);
bool is_on_dstack(dcontext_t *dcontext, byte *esp);
bool is_currently_on_dstack(dcontext_t *dcontext);
#ifdef WINDOWS
extern bool dr_early_injected;
extern int dr_early_injected_location;
extern bool dr_earliest_injected;
extern bool dr_injected_primary_thread;
extern bool dr_injected_secondary_thread;
extern bool dr_late_injected_primary_thread;
#endif
#ifdef RETURN_AFTER_CALL
extern bool dr_preinjected;
#endif
/* flags to indicate when DR is being initialized / exited using the API */
extern bool dr_api_entry;
extern bool dr_api_exit;
/* in dynamo.c */
/* 12-bit addressed hash table takes up 16K, has capacity of 4096.
* XXX: We currently never resize, assuming won't be seeing more than
* a few thousand threads: it should be simple to swap for a resizing
* table using generic_table_t though.
*/
#define ALL_THREADS_HASH_BITS 12
extern thread_record_t **all_threads;
extern mutex_t all_threads_lock;
DYNAMORIO_EXPORT int dynamorio_app_init(void);
int dynamorio_app_exit(void);
#if defined(CLIENT_INTERFACE) || defined(STANDALONE_UNIT_TEST)
dcontext_t * standalone_init(void);
void standalone_exit(void);
#endif
thread_record_t * thread_lookup(thread_id_t tid);
void add_thread(IF_WINDOWS_ELSE_NP(HANDLE hthread, process_id_t pid),
thread_id_t tid, bool under_dynamo_control, dcontext_t *dcontext);
bool remove_thread(IF_WINDOWS_(HANDLE hthread) thread_id_t tid);
uint get_thread_num(thread_id_t tid);
int get_num_threads(void);
bool is_last_app_thread(void);
void get_list_of_threads(thread_record_t ***list, int *num);
bool is_thread_known(thread_id_t tid);
#ifdef UNIX
void get_list_of_threads_ex(thread_record_t ***list, int *num, bool include_execve);
void mark_thread_execve(thread_record_t *tr, bool execve);
#endif
bool is_thread_initialized(void);
int dynamo_thread_init(byte *dstack_in, priv_mcontext_t *mc
_IF_CLIENT_INTERFACE(bool client_thread));
int dynamo_thread_exit(void);
void dynamo_thread_stack_free_and_exit(byte *stack);
int dynamo_other_thread_exit(thread_record_t *tr
_IF_WINDOWS(bool detach_stacked_callbacks));
void dynamo_thread_under_dynamo(dcontext_t *dcontext);
void dynamo_thread_not_under_dynamo(dcontext_t *dcontext);
/* used for synch to prevent thread creation/deletion in critical periods */
extern mutex_t thread_initexit_lock;
dcontext_t * create_new_dynamo_context(bool initial, byte *dstack_in,
priv_mcontext_t *mc);
void initialize_dynamo_context(dcontext_t *dcontext);
dcontext_t * create_callback_dcontext(dcontext_t *old_dcontext);
int dynamo_nullcalls_exit(void);
int dynamo_process_exit(void);
#ifdef UNIX
void dynamorio_fork_init(dcontext_t *dcontext);
#endif
void dynamorio_take_over_threads(dcontext_t *dcontext);
dr_statistics_t * get_dr_stats(void);
/* functions needed by detach */
int dynamo_shared_exit(thread_record_t *toexit
_IF_WINDOWS(bool detach_stacked_callbacks));
/* perform exit tasks that require full thread data structs */
void dynamo_process_exit_with_thread_info(void);
/* thread cleanup prior to clean exit event */
void dynamo_thread_exit_pre_client(dcontext_t *dcontext, thread_id_t id);
void dynamo_exit_post_detach(void);
/* enter/exit DR hooks */
void entering_dynamorio(void);
void exiting_dynamorio(void);
void handle_system_call(dcontext_t *dcontext);
/* self-protection */
void protect_data_section(uint sec, bool writable);
#ifdef DEBUG
const char *get_data_section_name(app_pc pc);
bool check_should_be_protected(uint sec);
# ifdef WINDOWS
bool data_sections_enclose_region(app_pc start, app_pc end);
# endif
#endif /* DEBUG */
/* all the locks used to protect shared data structures during multi-operation
* sequences, exported so that micro-operations can assert that one is held
*/
extern mutex_t bb_building_lock;
extern volatile bool bb_lock_start;
extern recursive_lock_t change_linking_lock;
/* where the current app thread's control is */
typedef enum {
WHERE_APP=0,
WHERE_INTERP,
WHERE_DISPATCH,
WHERE_MONITOR,
WHERE_SYSCALL_HANDLER,
WHERE_SIGNAL_HANDLER,
WHERE_TRAMPOLINE,
WHERE_CONTEXT_SWITCH,
WHERE_IBL,
WHERE_FCACHE,
WHERE_CLEAN_CALLEE,
WHERE_UNKNOWN,
#ifdef HOT_PATCHING_INTERFACE
WHERE_HOTPATCH,
#endif
WHERE_LAST
} where_am_i_t;
/* make args easier to read for protection change calls
* since only two possibilities not using new type
*/
enum {
READONLY=false,
WRITABLE=true
};
/* Values for unprotected_context_t.exit_reason, stored in a ushort. */
enum {
/* Default. All other reasons must clear after setting. */
EXIT_REASON_SELFMOD = 0,
/* Floating-point state PC needs updating (i#698). */
EXIT_REASON_FLOAT_PC_FNSAVE,
EXIT_REASON_FLOAT_PC_FXSAVE,
EXIT_REASON_FLOAT_PC_FXSAVE64,
EXIT_REASON_FLOAT_PC_XSAVE,
EXIT_REASON_FLOAT_PC_XSAVE64,
/* Additional types of system call gateways. */
EXIT_REASON_NI_SYSCALL_INT_0x81,
EXIT_REASON_NI_SYSCALL_INT_0x82,
/* Single step exception needs to be forged. */
EXIT_REASON_SINGLE_STEP,
};
/* Number of nested calls into native modules that we support. This number
* needs to equal the number of stubs in x86.asm:back_from_native_retstubs,
* which is checked at startup in native_exec.c.
* FIXME: Remove this limitation if we ever need to support true mutual
* recursion between native and non-native modules.
*/
enum { MAX_NATIVE_RETSTACK = 10 };
typedef struct _retaddr_and_retloc_t {
app_pc retaddr;
app_pc retloc;
} retaddr_and_retloc_t;
/* To handle TRY/EXCEPT/FINALLY setjmp */
typedef struct try_except_context_t {
/* FIXME: we are using a local dr_jmp_buf which is relatively
* small so minimal risk of dstack pressure. Alternatively, we
* can disallow nesting and have a single buffer per dcontext.
*/
/* N.B.: offsetof(try_except_context_t, context) is hardcoded in asm_defines.asm */
dr_jmp_buf_t context;
struct try_except_context_t *prev_context;
} try_except_context_t;
/* We do support TRY pre-dynamo_initialized via this global struct.
* This, along with safe_read pc ranges, satisfies most TRY uses that
* don't have a dcontext (i#350).
*/
typedef struct _try_except_t {
try_except_context_t *try_except_state; /* for TRY/EXCEPT/FINALLY */
bool unwinding_exception; /* NYI support for TRY/FINALLY -
* marks exception until an EXCEPT handles */
} try_except_t;
extern try_except_t global_try_except;
typedef struct {
/* WARNING: if you change the offsets of any of these fields,
* you must also change the offsets in <arch>/<arch.s>
*/
priv_mcontext_t mcontext; /* real machine context (in arch_exports.h) */
#ifdef UNIX
int dr_errno; /* errno used for DR (no longer used for app) */
#endif
bool at_syscall; /* for shared deletion syscalls_synch_flush,
* as well as syscalls handled from dispatch,
* and for reset to identify when at syscalls
*/
ushort exit_reason; /* Allows multiplexing LINK_SPECIAL_EXIT */
/* Above fields are padded to 8 bytes on all archs except Win x86-32. */
#ifdef CLIENT_INTERFACE
/* Spill slots for inlined clean calls. */
reg_t inline_spill_slots[CLEANCALL_NUM_INLINE_SLOTS];
#endif
} unprotected_context_t;
/* dynamo-specific context associated with each active app thread
* N.B.: make sure to update these routines as necessary if
* you add or remove fields:
* create_new_dynamo_context
* create_callback_dcontext
* initialize_dynamo_context
* swap_dcontexts
* if you add any pointers to data structures, make sure callback_setup()
* clears them to prevent stale pointers on callback return
*/
struct _dcontext_t {
/* NOTE: For any field to survive across callback stack switches it must either
* be indirected through a modular field or explicitly copied in
* create_callback_dcontext() (like the modular fields are).
*/
/* WARNING: if you change the offsets of any of these fields, up through
* ignore_enterexit, you must also change the offsets in <arch>/<arch.s>
*/
/* if SELFPROT_DCONTEXT, must split dcontext into unprotected and
* protected fields depending on whether they must be read-only
* when in the code cache.
* we waste sizeof(unprotected_context_t) bytes to provide runtime flexibility:
*/
union {
/* we use separate_upcontext if
* (TEST(SELFPROT_DCONTEXT, dynamo_options.protect_mask))
* else we use the inlined upcontext
*/
unprotected_context_t *separate_upcontext;
unprotected_context_t upcontext;
} upcontext;
/* HACK for x86.asm lack of runtime param access: this is either
* a self-ptr (to inlined upcontext) or if we separate upcontext it points there.
*/
unprotected_context_t *upcontext_ptr;
/* The next application pc to execute.
* Also used to store the cache pc to execute when entering the code cache,
* and set to the sentinel value BACK_TO_NATIVE_AFTER_SYSCALL for native_exec.
* FIXME: change to a union?
*/
app_pc next_tag;
linkstub_t * last_exit; /* last exit from cache */
byte * dstack; /* thread-private dynamo stack */
bool is_exiting; /* flag for exiting thread */
#ifdef WINDOWS
# ifdef CLIENT_INTERFACE
/* i#249: TEB field isolation */
int app_errno;
void * app_fls_data;
void * priv_fls_data;
void * app_nt_rpc;
void * priv_nt_rpc;
void * app_nls_cache;
void * priv_nls_cache;
# endif
void * app_stack_limit;
void * app_stack_base;
/* we need this to restore ptrs for other threads on detach */
byte * teb_base;
/* storage for an extra app value around sysenter system calls for the
* case 5441 Sygate interoperability hack */
/* FIXME - this needs to be moved into the upcontext as is written to
* in cache by ignore/shared_syscall, ramifications? */
app_pc sysenter_storage;
/* used to avoid enter/exit hooks for certain system calls (see case 4942) */
bool ignore_enterexit;
#endif
/* Coarse-grain cache exits require extra state storage as they do not
* use per-exit separate data structures
*/
union {
/* Indirect branches store on exit the source tag (with the type of
* branch coming from fake linkstubs), while direct store the source unit
*/
app_pc src_tag;
coarse_info_t *dir_exit;
} coarse_exit;
where_am_i_t whereami; /* where control is at the moment */
#ifdef UNIX
char signals_pending; /* != 0: pending; < 0: currently handling one */
#endif
/************* end of offset-crucial fields *********************/
/* FIXME: now that we initialize a new thread's dcontext right away, and
* a new callback's as well, we should be able to get rid of this
*/
bool initialized; /* has this context been used yet? */
thread_id_t owning_thread;
#ifdef UNIX
process_id_t owning_process; /* handle shared address space w/o shared pid */
#endif
#ifdef MACOS
uint thread_port; /* mach_port_t */
#endif
thread_record_t *thread_record; /* so don't have to do a thread_lookup */
void * allocated_start; /* used for cache alignment */
fragment_t * last_fragment; /* cached value of linkstub_fragment(last_exit) */
int sys_num; /* holds normalized syscall number */
#ifdef WINDOWS
reg_t * sys_param_base; /* used for post_system_call */
#endif
#if defined(UNIX) || defined(X64)
reg_t sys_param0; /* used for post_system_call */
reg_t sys_param1; /* used for post_system_call */
reg_t sys_param2; /* used for post_system_call */
reg_t sys_param3; /* used for post_system_call */
#endif
#ifdef UNIX
reg_t sys_param4; /* used for post_system_call i#173 */
bool sys_was_int; /* was the last system call via do_int_syscall? */
bool sys_xbp; /* PR 313715: store orig xbp */
# ifdef DEBUG
bool mprot_multi_areas; /* PR 410921: mprotect of 2 or more vmareas? */
# endif
#endif
#ifdef MACOS
reg_t app_xdx; /* stores orig xdx during sysenter */
#endif
/* Holds the ISA mode of the thread.
* For x86, default is to decode as base platform, but we want runtime ability to
* decode/encode 32-bit from 64-bit dynamorio.dll (we don't support the
* other way around: PR 236203). For ARM we must support swapping.
*/
dr_isa_mode_t isa_mode;
#ifdef ARM
/* Extra state (e.g., IT block state) used for decode/encode
* The actual type is not uint, we use them for better abstraction
* and better performace (avoiding a void * with separate allocation).
*/
uint encode_state[2]; /* encode_state_t in arm/decode_private.h */
uint decode_state[2]; /* decode_state_t in arm/decode_private.h */
#endif
/* to make things more modular these are void*: */
void * link_field;
void * monitor_field;
void * fcache_field;
void * fragment_field;
void * heap_field;
void * vm_areas_field;
void * os_field;
void * synch_field;
#ifdef UNIX
void * signal_field;
void * pcprofile_field;
#endif
void * private_code; /* various thread-private routines */
#ifdef TRACE_HEAD_CACHE_INCR
cache_pc trace_head_pc; /* HACK to jmp to trace head w/o a prefix */
#endif
#ifdef WINDOWS
/* these fields used for "stack" of contexts for callbacks */
# ifdef DCONTEXT_IN_EDI
dcontext_t *next_saved;
# endif
dcontext_t *prev_unused;
/* need to be able to tell which dcontexts in callback stack are valid */
bool valid;
/* special slot used to deal with callback returns, where we want to
* restore state of prior guy on callback stack, yet need current state
* to restore native state prior to callback return interrupt/syscall.
* Also used as temp next_tag slot for fcache_enter_indirect and cb ret.
*/
reg_t nonswapped_scratch;
#endif
/* next_tag holds the do_syscall entry point, so we need another
* slot to hold asynch targets for APCs to know next target and
* for NtContinue and sigreturn to set next target
*/
app_pc asynch_target;
/* must store post-intercepted-syscall target to allow using normal
* dispatch() for native_exec syscalls
*/
app_pc native_exec_postsyscall;
/* Stack of app return addresses and stack locations of callsites where we
* called into a native module.
*/
retaddr_and_retloc_t native_retstack[MAX_NATIVE_RETSTACK];
uint native_retstack_cur;
#ifdef PROGRAM_SHEPHERDING
bool alloc_no_reserve; /* to implement executable_if_alloc policy */
#endif
#ifdef CUSTOM_TRACES_RET_REMOVAL
int num_calls;
int num_rets;
int call_depth;
#endif
#ifdef CHECK_RETURNS_SSE2
int call_depth;
void * call_stack;
#endif
#ifdef DEBUG
file_t logfile;
thread_local_statistics_t * thread_stats;
bool expect_last_syscall_to_fail;
/* HACK to avoid recursion on pclookup for target invoking disassembly
* during decode_fragment() for a coarse target
*/
bool in_opnd_disassemble;
#endif /* DEBUG */
#ifdef DEADLOCK_AVOIDANCE
thread_locks_t * thread_owned_locks;
#endif
#ifdef KSTATS
thread_kstats_t * thread_kstats;
#endif
#ifdef PROFILE_RDTSC
uint64 cache_enter_time;
uint64 start_time; /* records start time for profiling */
fragment_t * prev_fragment;
/* top ten times spent in cache */
uint64 cache_frag_count; /* num frag execs in single cache period */
uint64 cache_time[10]; /* top ten times spent in cache */
uint64 cache_count[10]; /* top ten cache_frag_counts */
#endif
#ifdef CLIENT_INTERFACE
/* client interface-specific data */
client_data_t *client_data;
# ifdef DEBUG
/* i#2237: on exit we delete client_data before some IS_CLIENT_THREAD asserts. */
bool is_client_thread_exiting;
# endif
#endif
/* FIXME trace_sysenter_exit is used to capture an exit from a trace that
* ends in a SYSENTER and to enable trace head marking. So it's really a
* monitor-centric variable. It's placed in the context for now so that
* it's not shared across contexts (as the monitor data is). Cross-context
* sharing of this field could cause inadvertent trace head marking,
* for example, during a callback. A longer-term fix may be to move it to
* a context-private non-shared monitor struct.
*/
bool trace_sysenter_exit;
/* DR sets this field to indicate that it's forging an exception that
* may appear to originate in DR but should be passed on to the app. */
app_pc forged_exception_addr;
/* DR sets this field to indicate that it should forge a single
* step exception when app comes to that address. */
app_pc single_step_addr;
#ifdef HOT_PATCHING_INTERFACE
/* Fix for case 5367. */
bool nudge_thread; /* True only if this is a nudge thread. */
dr_jmp_buf_t hotp_excpt_state; /* To handle hot patch exceptions. */
#endif
try_except_t try_except; /* for TRY/EXCEPT/FINALLY */
#ifdef WINDOWS
/* for ASLR_SHARED_CONTENT, note per callback, not per thread to
* track properties of a syscall or a syscall pair. Even we don't
* expect to get APCs or callbacks while processing normal DLLs
* this should be per dcontext.
*/
aslr_syscall_context_t aslr_context;
/* Initially memset to 0 in create dcontext. If this is a nudge (or
* internal detach) thread (as detected by start address in intercept_apc),
* nudge_target is set to the corresponding nudge routine (currently always
* generic_nudge_target). We can then check this
* value in those routines after we come out of the cache as a security
* measure (xref case 552). This gives us some protection against an
* attacker leveraging our own detach routines and the like. FIXME - if
* the attacker is able to specify the start address for a newly created
* thread then they can fake this. */
void *nudge_target;
/* If free_app_stack is set, we free the application stack during thread exit
* cleanup. Used for nudge threads. */
bool free_app_stack;