FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
shareSQL/dbug/dbug.c at master · FlashSQL/shareSQL · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
FlashSQL
/
shareSQL
Public
Notifications
You must be signed in to change notification settings
Fork
4
Star
26
Code
Issues
0
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
shareSQL
/
dbug
/
dbug.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
2510 lines (2242 loc) · 65.5 KB
Breadcrumbs
shareSQL
/
dbug
/
dbug.c
Copy path
File metadata and controls
2510 lines (2242 loc) · 65.5 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
/******************************************************************************
* *
* N O T I C E *
* *
* Copyright Abandoned, 1987, Fred Fish *
* *
* *
* This previously copyrighted work has been placed into the public *
* domain by the author and may be freely used for any purpose, *
* private or commercial. *
* *
* Because of the number of inquiries I was receiving about the use *
* of this product in commercially developed works I have decided to *
* simply make it public domain to further its unrestricted use. I *
* specifically would be most happy to see this material become a *
* part of the standard Unix distributions by AT&T and the Berkeley *
* Computer Science Research Group, and a standard part of the GNU *
* system from the Free Software Foundation. *
* *
* I would appreciate it, as a courtesy, if this notice is left in *
* all copies and derivative works. Thank you. *
* *
* The author makes no warranty of any kind with respect to this *
* product and explicitly disclaims any implied warranties of mer- *
* chantability or fitness for any particular purpose. *
* *
******************************************************************************
*/
/*
* FILE
*
* dbug.c runtime support routines for dbug package
*
* SCCS
*
* @(#)dbug.c 1.25 7/25/89
*
* DESCRIPTION
*
* These are the runtime support routines for the dbug package.
* The dbug package has two main components; the user include
* file containing various macro definitions, and the runtime
* support routines which are called from the macro expansions.
*
* Externally visible functions in the runtime support module
* use the naming convention pattern "_db_xx...xx_", thus
* they are unlikely to collide with user defined function names.
*
* AUTHOR(S)
*
* Fred Fish (base code)
* Enhanced Software Technologies, Tempe, AZ
* asuvax!mcdphx!estinc!fnf
*
* Binayak Banerjee (profiling enhancements)
* seismo!bpa!sjuvax!bbanerje
*
* Michael Widenius:
* DBUG_DUMP - To dump a block of memory.
* PUSH_FLAG "O" - To be used insted of "o" if we
* want flushing after each write
* PUSH_FLAG "A" - as 'O', but we will append to the out file instead
* of creating a new one.
* Check of malloc on entry/exit (option "S")
*
* Sergei Golubchik:
* DBUG_EXECUTE_IF
* incremental mode (-#+t:-d,info ...)
* DBUG_SET, _db_explain_
* thread-local settings
* negative lists (-#-d,info => everything but "info")
*
* function/ syntax
* (the logic is - think of a call stack as of a path.
* "function" means only this function, "function/" means the hierarchy.
* in the future, filters like function1/function2 could be supported.
* following this logic glob(7) wildcards are supported.)
*
*/
#include
<my_global.h>
#include
<m_string.h>
#include
<errno.h>
#ifdef
HAVE_FNMATCH_H
#include
<fnmatch.h>
#else
#define
fnmatch
(
A
,
B
,
C
) strcmp(A,B)
#endif
#if
defined(
__WIN__
)
#include
<process.h>
#endif
#ifndef
DBUG_OFF
/*
* Manifest constants which may be "tuned" if desired.
*/
#define
PRINTBUF
1024
/* Print buffer size */
#define
INDENT
2
/* Indentation per trace level */
#define
MAXDEPTH
200
/* Maximum trace depth default */
/*
* The following flags are used to determine which
* capabilities the user has enabled with the settings
* push macro.
*
* TRACE_ON is also used in _db_stack_frame_->level
* (until we add flags to _db_stack_frame_, increasing it by 4 bytes)
*/
#define
DEBUG_ON
(1 << 1)
/* Debug enabled */
#define
FILE_ON
(1 << 2)
/* File name print enabled */
#define
LINE_ON
(1 << 3)
/* Line number print enabled */
#define
DEPTH_ON
(1 << 4)
/* Function nest level print enabled */
#define
PROCESS_ON
(1 << 5)
/* Process name print enabled */
#define
NUMBER_ON
(1 << 6)
/* Number each line of output */
#define
PROFILE_ON
(1 << 7)
/* Print out profiling code */
#define
PID_ON
(1 << 8)
/* Identify each line with process id */
#define
TIMESTAMP_ON
(1 << 9)
/* timestamp every line of output */
#define
FLUSH_ON_WRITE
(1 << 10)
/* Flush on every write */
#define
OPEN_APPEND
(1 << 11)
/* Open for append */
#define
TRACE_ON
((uint)1 << 31)
/* Trace enabled. MUST be the highest bit!*/
#define
TRACING
(cs->stack->flags & TRACE_ON)
#define
DEBUGGING
(cs->stack->flags & DEBUG_ON)
#define
PROFILING
(cs->stack->flags & PROFILE_ON)
/*
* Typedefs to make things more obvious.
*/
#define
BOOLEAN
my_bool
/*
* Make it easy to change storage classes if necessary.
*/
#define
IMPORT
extern
/* Names defined externally */
#define
EXPORT
/* Allocated here, available globally */
#define
AUTO
auto
/* Names to be allocated on stack */
#define
REGISTER
register
/* Names to be placed in registers */
/*
* The default file for profiling. Could also add another flag
* (G?) which allowed the user to specify this.
*
* If the automatic variables get allocated on the stack in
* reverse order from their declarations, then define AUTOS_REVERSE to 1.
* This is used by the code that keeps track of stack usage. For
* forward allocation, the difference in the dbug frame pointers
* represents stack used by the callee function. For reverse allocation,
* the difference represents stack used by the caller function.
*
*/
#define
PROF_FILE
"dbugmon.out"
#define
PROF_EFMT
"E\t%ld\t%s\n"
#define
PROF_SFMT
"S\t%lx\t%lx\t%s\n"
#define
PROF_XFMT
"X\t%ld\t%s\n"
#ifdef
M_I386
/* predefined by xenix 386 compiler */
#define
AUTOS_REVERSE
1
#else
#define
AUTOS_REVERSE
0
#endif
/*
* Externally supplied functions.
*/
#ifndef
HAVE_PERROR
static
void
perror
();
/* Fake system/library error print routine */
#endif
/*
* The user may specify a list of functions to trace or
* debug. These lists are kept in a linear linked list,
* a very simple implementation.
*/
struct
link
{
struct
link
*
next_link
;
/* Pointer to the next link */
char
flags
;
char
str
[
1
];
/* Pointer to link's contents */
};
/* flags for struct link and return flags of InList */
#define
SUBDIR
1
/* this MUST be 1 */
#define
INCLUDE
2
#define
EXCLUDE
4
/* this is not a struct link flag, but only a return flags of InList */
#define
MATCHED
65536
#define
NOT_MATCHED
0
/*
* Debugging settings can be pushed or popped off of a
* stack which is implemented as a linked list. Note
* that the head of the list is the current settings and the
* stack is pushed by adding a new settings to the head of the
* list or popped by removing the first link.
*
* Note: if out_file is NULL, the other fields are not initialized at all!
*/
struct
settings
{
uint
flags
;
/* Current settings flags */
uint
maxdepth
;
/* Current maximum trace depth */
uint
delay
;
/* Delay after each output line */
uint
sub_level
;
/* Sub this from code_state->level */
FILE
*
out_file
;
/* Current output stream */
FILE
*
prof_file
;
/* Current profiling stream */
char
name
[
FN_REFLEN
];
/* Name of output file */
struct
link
*
functions
;
/* List of functions */
struct
link
*
p_functions
;
/* List of profiled functions */
struct
link
*
keywords
;
/* List of debug keywords */
struct
link
*
processes
;
/* List of process names */
struct
settings
*
next
;
/* Next settings in the list */
};
#define
is_shared
(
S
,
V
) ((S)->next && (S)->next->V == (S)->V)
/*
* Local variables not seen by user.
*/
static
BOOLEAN
init_done
=
FALSE;
/* Set to TRUE when initialization done */
/**
Global debugging settings.
This structure shared between all threads,
and is the last element in each thread @c CODE_STATE::stack chain.
Protected by @c THR_LOCK_init_settings.
*/
static
struct
settings
init_settings
;
static
const
char
*
db_process
=
0
;
/* Pointer to process name; argv[0] */
my_bool
_dbug_on_
=
TRUE;
/* FALSE if no debugging at all */
typedef
struct
_db_code_state_
{
const
char
*
process
;
/* Pointer to process name; usually argv[0] */
const
char
*
func
;
/* Name of current user function */
const
char
*
file
;
/* Name of current user file */
struct
_db_stack_frame_
*
framep
;
/* Pointer to current frame */
struct
settings
*
stack
;
/* debugging settings */
const
char
*
jmpfunc
;
/* Remember current function for setjmp */
const
char
*
jmpfile
;
/* Remember current file for setjmp */
int
lineno
;
/* Current debugger output line number */
uint
level
;
/* Current function nesting level */
int
jmplevel
;
/* Remember nesting level at setjmp() */
/*
* The following variables are used to hold the state information
* between the call to _db_pargs_() and _db_doprnt_(), during
* expansion of the DBUG_PRINT macro. This is the only macro
* that currently uses these variables.
*
* These variables are currently used only by _db_pargs_() and
* _db_doprnt_().
*/
uint
u_line
;
/* User source code line number */
int
locked
;
/* If locked with _db_lock_file_ */
const
char
*
u_keyword
;
/* Keyword for current macro */
uint
m_read_lock_count
;
}
CODE_STATE
;
/*
The test below is so we could call functions with DBUG_ENTER before
my_thread_init().
*/
#define
get_code_state_if_not_set_or_return
if (!cs && !((cs=code_state()))) return
#define
get_code_state_or_return
if (!((cs=code_state()))) return
/* Handling lists */
#define
ListAdd
(
A
,
B
,
C
) ListAddDel(A,B,C,INCLUDE)
#define
ListDel
(
A
,
B
,
C
) ListAddDel(A,B,C,EXCLUDE)
static
struct
link
*
ListAddDel
(
struct
link
*
,
const
char
*
,
const
char
*
,
int
);
static
struct
link
*
ListCopy
(
struct
link
*
);
static
int
InList
(
struct
link
*
linkp
,
const
char
*
cp
);
static
uint
ListFlags
(
struct
link
*
linkp
);
static
void
FreeList
(
struct
link
*
linkp
);
/* OpenClose debug output stream */
static
void
DBUGOpenFile
(
CODE_STATE
*
,
const
char
*
,
const
char
*
,
int
);
static
void
DBUGCloseFile
(
CODE_STATE
*
cs
,
FILE
*
fp
);
/* Push current debug settings */
static
void
PushState
(
CODE_STATE
*
cs
);
/* Free memory associated with debug state. */
static
void
FreeState
(
CODE_STATE
*
cs
,
struct
settings
*
state
,
int
free_state
);
/* Test for tracing enabled */
static
int
DoTrace
(
CODE_STATE
*
cs
);
/*
return values of DoTrace.
Can also be used as bitmask: ret & DO_TRACE
*/
#define
DO_TRACE
1
#define
DONT_TRACE
2
#define
ENABLE_TRACE
3
#define
DISABLE_TRACE
4
/* Test to see if file is writable */
#if
defined(
HAVE_ACCESS
)
static
BOOLEAN
Writable
(
const
char
*
pathname
);
/* Change file owner and group */
static
void
ChangeOwner
(
CODE_STATE
*
cs
,
char
*
pathname
);
/* Allocate memory for runtime support */
#endif
static
void
DoPrefix
(
CODE_STATE
*
cs
,
uint
line
);
static
char
*
DbugMalloc
(
size_t
size
);
static
const
char
*
BaseName
(
const
char
*
pathname
);
static
void
Indent
(
CODE_STATE
*
cs
,
int
indent
);
static
void
DbugFlush
(
CODE_STATE
*
);
static
void
DbugExit
(
const
char
*
why
);
static
const
char
*
DbugStrTok
(
const
char
*
s
);
static
void
DbugVfprintf
(
FILE
*
stream
,
const
char
*
format
,
va_list
args
);
/*
* Miscellaneous printf format strings.
*/
#define
ERR_MISSING_RETURN
"missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
#define
ERR_MISSING_UNLOCK
"missing DBUG_UNLOCK_FILE macro in function \"%s\"\n"
#define
ERR_OPEN
"%s: can't open debug output stream \"%s\": "
#define
ERR_CLOSE
"%s: can't close debug file: "
#define
ERR_ABORT
"%s: debugger aborting because %s\n"
/*
* Macros and defines for testing file accessibility under UNIX and MSDOS.
*/
#undef
EXISTS
#if
!defined(
HAVE_ACCESS
)
#define
EXISTS
(
pathname
) (FALSE)
/* Assume no existance */
#define
Writable
(
name
) (TRUE)
#else
#define
EXISTS
(
pathname
) (access(pathname, F_OK) == 0)
#define
WRITABLE
(
pathname
) (access(pathname, W_OK) == 0)
#endif
/*
** Macros to allow dbugging with threads
*/
#include
<my_pthread.h>
static
pthread_mutex_t
THR_LOCK_dbug
;
/**
A mutex protecting flushing of gcov data, see _db_flush_gcov_().
We don't re-use THR_LOCK_dbug, because that would disallow:
DBUG_LOCK_FILE; ..... DBUG_SUICIDE(); .... DBUG_UNLOCK_FILE;
*/
static
pthread_mutex_t
THR_LOCK_gcov
;
/**
Lock, to protect @c init_settings.
For performance reasons,
the member @c init_settings.flags is not protected.
*/
static
rw_lock_t
THR_LOCK_init_settings
;
static
CODE_STATE
*
code_state
(
void
)
{
CODE_STATE
*
cs
,
*
*
cs_ptr
;
/*
_dbug_on_ is reset if we don't plan to use any debug commands at all and
we want to run on maximum speed
*/
if
(!
_dbug_on_
)
return
0
;
if
(!
init_done
)
{
init_done
=
TRUE;
pthread_mutex_init
(
&
THR_LOCK_dbug
,
NULL
);
pthread_mutex_init
(
&
THR_LOCK_gcov
,
NULL
);
my_rwlock_init
(
&
THR_LOCK_init_settings
,
NULL
);
memset
(
&
init_settings
,
0
,
sizeof
(
init_settings
));
init_settings
.
out_file
=
stderr
;
init_settings
.
flags
=
OPEN_APPEND
;
}
if
(!(
cs_ptr
=
(
CODE_STATE
*
*
)
my_thread_var_dbug
()))
return
0
;
/* Thread not initialised */
if
(!(
cs
=
*
cs_ptr
))
{
cs
=
(
CODE_STATE
*
)
DbugMalloc
(
sizeof
(
*
cs
));
memset
(
cs
,
0
,
sizeof
(
*
cs
));
cs
->
process
=
db_process
?
db_process
:
"dbug"
;
cs
->
func
=
"?func"
;
cs
->
file
=
"?file"
;
cs
->
stack
=
&
init_settings
;
cs
->
m_read_lock_count
=
0
;
*
cs_ptr
=
cs
;
}
return
cs
;
}
/**
Lock the stack debugging settings.
Only the shared (global) settings are locked if necessary,
per thread settings are local and safe to use.
This lock is re entrant.
@sa unlock_stack
*/
static
void
read_lock_stack
(
CODE_STATE
*
cs
)
{
if
(
cs
->
stack
==
&
init_settings
)
{
if
(
++
(
cs
->
m_read_lock_count
)
==
1
)
rw_rdlock
(
&
THR_LOCK_init_settings
);
}
}
/**
Unlock the stack debugging settings.
@sa read_lock_stack
*/
static
void
unlock_stack
(
CODE_STATE
*
cs
)
{
if
(
cs
->
stack
==
&
init_settings
)
{
if
(
--
(
cs
->
m_read_lock_count
)
==
0
)
rw_unlock
(
&
THR_LOCK_init_settings
);
}
}
/*
* Translate some calls among different systems.
*/
#ifdef
HAVE_SLEEP
/* sleep() wants seconds */
#define
Delay
(
A
) sleep(((uint) A)/10)
#else
#define
Delay
(
A
) (0)
#endif
/*
* FUNCTION
*
* _db_process_ give the name to the current process/thread
*
* SYNOPSIS
*
* VOID _process_(name)
* char *name;
*
*/
void
_db_process_
(
const
char
*
name
)
{
CODE_STATE
*
cs
;
if
(!
db_process
)
db_process
=
name
;
get_code_state_or_return
;
cs
->
process
=
name
;
}
/*
* FUNCTION
*
* DbugParse parse control string and set current debugger settings
*
* DESCRIPTION
*
* Given pointer to a debug control string in "control",
* parses the control string, and sets
* up a current debug settings.
*
* The debug control string is a sequence of colon separated fields
* as follows:
*
* [+]<field_1>:<field_2>:...:<field_N>
*
* Each field consists of a mandatory flag character followed by
* an optional "," and comma separated list of modifiers:
*
* [sign]flag[,modifier,modifier,...,modifier]
*
* See the manual for the list of supported signs, flags, and modifiers
*
* For convenience, any leading "-#" is stripped off.
*
* RETURN
* 1 - a list of functions ("f" flag) was possibly changed
* 0 - a list of functions was not changed
*/
int
DbugParse
(
CODE_STATE
*
cs
,
const
char
*
control
)
{
const
char
*
end
;
int
rel
,
f_used
=
0
;
struct
settings
*
stack
;
/*
Make sure we are not changing settings while inside a
DBUG_LOCK_FILE
DBUG_UNLOCK_FILE
section, that is a mis use, that would cause changing
DBUG_FILE while the caller prints to it.
*/
assert
(!
cs
->
locked
);
stack
=
cs
->
stack
;
/*
When parsing the global init_settings itself,
make sure to block every other thread using dbug functions.
*/
assert
(
cs
->
m_read_lock_count
==
0
);
if
(
stack
==
&
init_settings
)
rw_wrlock
(
&
THR_LOCK_init_settings
);
if
(
control
[
0
]
==
'-'
&&
control
[
1
]
==
'#'
)
control
+=
2
;
rel
=
control
[
0
]
==
'+'
||
control
[
0
]
==
'-'
;
if
((!
rel
||
(!
stack
->
out_file
&&
!
stack
->
next
)))
{
/* Free memory associated with the state before resetting its members */
FreeState
(
cs
,
stack
,
0
);
stack
->
flags
=
0
;
stack
->
delay
=
0
;
stack
->
maxdepth
=
0
;
stack
->
sub_level
=
0
;
stack
->
out_file
=
stderr
;
stack
->
prof_file
=
NULL
;
stack
->
functions
=
NULL
;
stack
->
p_functions
=
NULL
;
stack
->
keywords
=
NULL
;
stack
->
processes
=
NULL
;
}
else
if
(!
stack
->
out_file
)
{
stack
->
flags
=
stack
->
next
->
flags
;
stack
->
delay
=
stack
->
next
->
delay
;
stack
->
maxdepth
=
stack
->
next
->
maxdepth
;
stack
->
sub_level
=
stack
->
next
->
sub_level
;
strcpy
(
stack
->
name
,
stack
->
next
->
name
);
stack
->
prof_file
=
stack
->
next
->
prof_file
;
if
(
stack
->
next
==
&
init_settings
)
{
assert
(
stack
!=
&
init_settings
);
rw_rdlock
(
&
THR_LOCK_init_settings
);
/*
Never share with the global parent - it can change under your feet.
Reset out_file to stderr to prevent sharing of trace files between
global and session settings.
*/
stack
->
out_file
=
stderr
;
stack
->
functions
=
ListCopy
(
init_settings
.
functions
);
stack
->
p_functions
=
ListCopy
(
init_settings
.
p_functions
);
stack
->
keywords
=
ListCopy
(
init_settings
.
keywords
);
stack
->
processes
=
ListCopy
(
init_settings
.
processes
);
rw_unlock
(
&
THR_LOCK_init_settings
);
}
else
{
stack
->
out_file
=
stack
->
next
->
out_file
;
stack
->
functions
=
stack
->
next
->
functions
;
stack
->
p_functions
=
stack
->
next
->
p_functions
;
stack
->
keywords
=
stack
->
next
->
keywords
;
stack
->
processes
=
stack
->
next
->
processes
;
}
}
end
=
DbugStrTok
(
control
);
while
(
control
<
end
)
{
int
c
,
sign
=
(
*
control
==
'+'
) ?
1
: (
*
control
==
'-'
) ?
-1
:
0
;
if
(
sign
)
control
++
;
c
=
*
control
++
;
if
(
*
control
==
','
)
control
++
;
/* XXX when adding new cases here, don't forget _db_explain_ ! */
switch
(
c
) {
case
'd'
:
if
(
sign
<
0
&&
control
==
end
)
{
if
(!
is_shared
(
stack
,
keywords
))
FreeList
(
stack
->
keywords
);
stack
->
keywords
=
NULL
;
stack
->
flags
&= ~
DEBUG_ON
;
break
;
}
if
(
rel
&&
is_shared
(
stack
,
keywords
))
stack
->
keywords
=
ListCopy
(
stack
->
keywords
);
if
(
sign
<
0
)
{
if
(
DEBUGGING
)
{
stack
->
keywords
=
ListDel
(
stack
->
keywords
,
control
,
end
);
/* Turn off DEBUG_ON if it is last keyword to be removed. */
if
(
stack
->
keywords
==
NULL
)
stack
->
flags
&= ~
DEBUG_ON
;
}
break
;
}
/* Do not add keyword if debugging all is enabled. */
if
(!(
DEBUGGING
&&
stack
->
keywords
==
NULL
))
{
stack
->
keywords
=
ListAdd
(
stack
->
keywords
,
control
,
end
);
stack
->
flags
|=
DEBUG_ON
;
}
/* If debug all is enabled, make the keyword list empty. */
if
(
sign
==
1
&&
control
==
end
)
{
FreeList
(
stack
->
keywords
);
stack
->
keywords
=
NULL
;
}
break
;
case
'D'
:
stack
->
delay
=
atoi
(
control
);
break
;
case
'f'
:
f_used
=
1
;
if
(
sign
<
0
&&
control
==
end
)
{
if
(!
is_shared
(
stack
,
functions
))
FreeList
(
stack
->
functions
);
stack
->
functions
=
NULL
;
break
;
}
if
(
rel
&&
is_shared
(
stack
,
functions
))
stack
->
functions
=
ListCopy
(
stack
->
functions
);
if
(
sign
<
0
)
stack
->
functions
=
ListDel
(
stack
->
functions
,
control
,
end
);
else
stack
->
functions
=
ListAdd
(
stack
->
functions
,
control
,
end
);
break
;
case
'F'
:
if
(
sign
<
0
)
stack
->
flags
&= ~
FILE_ON
;
else
stack
->
flags
|=
FILE_ON
;
break
;
case
'i'
:
if
(
sign
<
0
)
stack
->
flags
&= ~
PID_ON
;
else
stack
->
flags
|=
PID_ON
;
break
;
case
'L'
:
if
(
sign
<
0
)
stack
->
flags
&= ~
LINE_ON
;
else
stack
->
flags
|=
LINE_ON
;
break
;
case
'n'
:
if
(
sign
<
0
)
stack
->
flags
&= ~
DEPTH_ON
;
else
stack
->
flags
|=
DEPTH_ON
;
break
;
case
'N'
:
if
(
sign
<
0
)
stack
->
flags
&= ~
NUMBER_ON
;
else
stack
->
flags
|=
NUMBER_ON
;
break
;
case
'A'
:
case
'O'
:
stack
->
flags
|=
FLUSH_ON_WRITE
;
/* fall through */
case
'a'
:
case
'o'
:
/* In case we already have an open file. */
if
(!
is_shared
(
stack
,
out_file
))
DBUGCloseFile
(
cs
,
stack
->
out_file
);
if
(
sign
<
0
)
{
stack
->
flags
&= ~
FLUSH_ON_WRITE
;
stack
->
out_file
=
stderr
;
break
;
}
if
(
c
==
'a'
||
c
==
'A'
)
stack
->
flags
|=
OPEN_APPEND
;
else
stack
->
flags
&= ~
OPEN_APPEND
;
if
(
control
!=
end
)
DBUGOpenFile
(
cs
,
control
,
end
,
stack
->
flags
&
OPEN_APPEND
);
else
DBUGOpenFile
(
cs
,
"-"
,
0
,
0
);
break
;
case
'p'
:
if
(
sign
<
0
&&
control
==
end
)
{
if
(!
is_shared
(
stack
,
processes
))
FreeList
(
stack
->
processes
);
stack
->
processes
=
NULL
;
break
;
}
if
(
rel
&&
is_shared
(
stack
,
processes
))
stack
->
processes
=
ListCopy
(
stack
->
processes
);
if
(
sign
<
0
)
stack
->
processes
=
ListDel
(
stack
->
processes
,
control
,
end
);
else
stack
->
processes
=
ListAdd
(
stack
->
processes
,
control
,
end
);
break
;
case
'P'
:
if
(
sign
<
0
)
stack
->
flags
&= ~
PROCESS_ON
;
else
stack
->
flags
|=
PROCESS_ON
;
break
;
case
'r'
:
stack
->
sub_level
=
cs
->
level
;
break
;
case
't'
:
if
(
sign
<
0
)
{
if
(
control
!=
end
)
stack
->
maxdepth
-=
atoi
(
control
);
else
stack
->
maxdepth
=
0
;
}
else
{
if
(
control
!=
end
)
stack
->
maxdepth
+=
atoi
(
control
);
else
stack
->
maxdepth
=
MAXDEPTH
;
}
if
(
stack
->
maxdepth
>
0
)
stack
->
flags
|=
TRACE_ON
;
else
stack
->
flags
&= ~
TRACE_ON
;
break
;
case
'T'
:
if
(
sign
<
0
)
stack
->
flags
&= ~
TIMESTAMP_ON
;
else
stack
->
flags
|=
TIMESTAMP_ON
;
break
;
}
if
(!
*
end
)
break
;
control
=
end
+
1
;
end
=
DbugStrTok
(
control
);
}
if
(
stack
->
next
==
&
init_settings
)
{
/*
Enforce nothing is shared with the global init_settings
*/
assert
((
stack
->
functions
==
NULL
)
||
(
stack
->
functions
!=
init_settings
.
functions
));
assert
((
stack
->
p_functions
==
NULL
)
||
(
stack
->
p_functions
!=
init_settings
.
p_functions
));
assert
((
stack
->
keywords
==
NULL
)
||
(
stack
->
keywords
!=
init_settings
.
keywords
));
assert
((
stack
->
processes
==
NULL
)
||
(
stack
->
processes
!=
init_settings
.
processes
));
}
if
(
stack
==
&
init_settings
)
rw_unlock
(
&
THR_LOCK_init_settings
);
return
!
rel
||
f_used
;
}
#define
framep_trace_flag
(
cs
,
frp
) (frp ? \
frp->level & TRACE_ON : \
(ListFlags(cs->stack->functions) & INCLUDE) ? \
0 : (uint)TRACE_ON)
void
FixTraceFlags_helper
(
CODE_STATE
*
cs
,
const
char
*
func
,
struct
_db_stack_frame_
*
framep
)
{
if
(
framep
->
prev
)
FixTraceFlags_helper
(
cs
,
framep
->
func
,
framep
->
prev
);
cs
->
func
=
func
;
cs
->
level
=
framep
->
level
&
~
TRACE_ON
;
framep
->
level
=
cs
->
level
|
framep_trace_flag
(
cs
,
framep
->
prev
);
/*
we don't set cs->framep correctly, even though DoTrace uses it.
It's ok, because cs->framep may only affect DO_TRACE/DONT_TRACE return
values, but we ignore them here anyway
*/
switch
(
DoTrace
(
cs
)) {
case
ENABLE_TRACE
:
framep
->
level
|=
TRACE_ON
;
break
;
case
DISABLE_TRACE
:
framep
->
level
&= ~
TRACE_ON
;
break
;
}
}
#define
fflags
(
cs
) cs->stack->out_file ? ListFlags(cs->stack->functions) : TRACE_ON;
void
FixTraceFlags
(
uint
old_fflags
,
CODE_STATE
*
cs
)
{
const
char
*
func
;
uint
new_fflags
,
traceon
,
level
;
struct
_db_stack_frame_
*
framep
;
/*
first (a.k.a. safety) check:
if we haven't started tracing yet, no call stack at all - we're safe.
*/
framep
=
cs
->
framep
;
if
(
framep
==
0
)
return
;
/*
Ok, the tracing has started, call stack isn't empty.
second check: does the new list have a SUBDIR rule ?
*/
new_fflags
=
fflags
(
cs
);
if
(
new_fflags
&
SUBDIR
)
goto
yuck
;
/*
Ok, new list doesn't use SUBDIR.
third check: we do NOT need to re-scan if
neither old nor new lists used SUBDIR flag and if a default behavior
(whether an unlisted function is traced) hasn't changed.
Default behavior depends on whether there're INCLUDE elements in the list.
*/
if
(!(
old_fflags
&
SUBDIR
)
&&
!((
new_fflags
^
old_fflags
)
&
INCLUDE
))
return
;
/*
Ok, old list may've used SUBDIR, or defaults could've changed.
fourth check: are we inside a currently active SUBDIR rule ?
go up the call stack, if TRACE_ON flag ever changes its value - we are.
*/
for
(
traceon
=
framep
->
level
;
framep
;
framep
=
framep
->
prev
)
if
((
traceon
^
framep
->
level
)
&
TRACE_ON
)
goto
yuck
;
/*
Ok, TRACE_ON flag doesn't change in the call stack.
fifth check: but is the top-most value equal to a default one ?
*/
if
(((
traceon
&
TRACE_ON
)
!=
0
)
==
((
new_fflags
&
INCLUDE
)
==
0
))
return
;
yuck
:
/*
Yuck! function list was changed, and one of the currently active rules
was possibly affected. For example, a tracing could've been enabled or
disabled for a function somewhere up the call stack.
To react correctly, we must go up the call stack all the way to
the top and re-match rules to set TRACE_ON bit correctly.
We must traverse the stack forwards, not backwards.
That's what a recursive helper is doing.
It'll destroy two CODE_STATE fields, save them now.
*/
func
=
cs
->
func
;
level
=
cs
->
level
;
FixTraceFlags_helper
(
cs
,
func
,
cs
->
framep
);
/* now we only need to restore CODE_STATE fields, and we're done */
cs
->
func
=
func
;
cs
->
level
=
level
;
}
/*
* FUNCTION
*
* _db_set_ set current debugger settings
*
* SYNOPSIS
*
* VOID _db_set_(control)
* char *control;
*
* DESCRIPTION
*
* Given pointer to a debug control string in "control",
* parses the control string, and sets up a current debug
* settings. Pushes a new debug settings if the current is
* set to the initial debugger settings.
*
*/
void
_db_set_
(
const
char
*
control
)
{
CODE_STATE
*
cs
;
uint
old_fflags
;
get_code_state_or_return
;
read_lock_stack
(
cs
);
old_fflags
=
fflags
(
cs
);
unlock_stack
(
cs
);
if
(
cs
->
stack
==
&
init_settings
)
PushState
(
cs
);
if
(
DbugParse
(
cs
,
control
))
{
read_lock_stack
(
cs
);
FixTraceFlags
(
old_fflags
,
cs
);
unlock_stack
(
cs
);
}
}
/*
* FUNCTION
*
* _db_push_ push current debugger settings and set up new one
*
* SYNOPSIS
*
* VOID _db_push_(control)
* char *control;
*
* DESCRIPTION
*
* Given pointer to a debug control string in "control", pushes
* the current debug settings, parses the control string, and sets
* up a new debug settings with DbugParse()
*
*/
void
_db_push_
(
const
char
*
control
)
{
CODE_STATE
*
cs
;
uint
old_fflags
;
get_code_state_or_return
;
read_lock_stack
(
cs
);
old_fflags
=
fflags
(
cs
);
unlock_stack
(
cs
);
PushState
(
cs
);
if
(
DbugParse
(
cs
,
control
))
{
read_lock_stack
(
cs
);
FixTraceFlags
(
old_fflags
,
cs
);
unlock_stack
(
cs
);
}
}
/**
Returns TRUE if session-local settings have been set.
*/
int
_db_is_pushed_
()
{
CODE_STATE
*
cs
=
NULL
;
get_code_state_or_return
FALSE
;
return
(
cs
->
stack
!=
&
init_settings
);
}
/*
* FUNCTION
*
* _db_set_init_ set initial debugger settings
*
* SYNOPSIS
*
* VOID _db_set_init_(control)
* char *control;
*
* DESCRIPTION
* see _db_set_
*
*/
void
_db_set_init_
(
const
char
*
control
)
{
CODE_STATE
tmp_cs
;
memset
(
&
tmp_cs
,
0
,
sizeof
(
tmp_cs
));
tmp_cs
.
stack
=
&
init_settings
;
tmp_cs
.
process
=
db_process
?
db_process
:
"dbug"
;
DbugParse
(
&
tmp_cs
,
control
);
}
/*
* FUNCTION
*
* _db_pop_ pop the debug stack
*
* DESCRIPTION
*
* Pops the debug stack, returning the debug settings to its
* condition prior to the most recent _db_push_ invocation.
* Note that the pop will fail if it would remove the last
View remainder of file in raw view
Back
|
FazBrowse Home
|
New Git URL