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
|
// Copyright (C) 2005, 2006 IBM Corp.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
// Public License (GPL); either version 2, or (at your option) any
// later version.
%{
#if defined(ASCII_TRACE)
#ifndef _FMT_
#define _FMT_ unsigned int
#endif
#else
#ifndef _FMT_
#define _FMT_ int64_t
#endif
#endif
%}
function lket_trace_header_init()
%{
/* header info for binary format*/
#if !defined(ASCII_TRACE)
#define MAGIC_NUMBER 0xAEFCDB6B
#define LKET_TRACE_VER_MAJOR 0x01
#define LKET_TRACE_VER_MINOR 0x01 /* used for user customization */
#define LITTLE_ENDIAN 0x01
#define BIG_ENDIAN 0x02
#define BITS_WIDTH 64 /* 32-bit or 64-bit environment*/
#define LKET_HEADER_LEN 0 /* fake number, bin_write will fill in the
actual length of trace header */
_stp_printf("%4b%2n%1b%1b%1b%1b", (_FMT_)MAGIC_NUMBER, (_FMT_)LKET_HEADER_LEN,
(_FMT_)LKET_TRACE_VER_MAJOR, (_FMT_)LKET_TRACE_VER_MINOR,
(_FMT_)BIG_ENDIAN, (_FMT_)BITS_WIDTH);
_stp_print_flush();
#endif
%}
function lket_trace_init()
{
lket_trace_header_init()
}
%{
#ifndef __LKET_TRACE__
#define __LKET_TRACE__
#define LKET_PKT_SYS 1
#define LKET_PKT_BT 2
#define LKET_PKT_USER 3
#define MAX_FMT_LEN 128
char new_sysfmt[MAX_FMT_LEN] = "\n%d|%d|%d|%d|%d|%d|%d|%d";
char new_userfmt[MAX_FMT_LEN] = "| USER:";
#define NEW_SYSFMT_START 24
#define NEW_USERFMT_START 7
void fmt_change(char *oldfmt, char *newfmt, int newfmt_start)
{
char *old_ptr, *new_ptr;
old_ptr = oldfmt;
new_ptr = newfmt + newfmt_start;
while(*old_ptr != 0 && (new_ptr - newfmt) < MAX_FMT_LEN) {
if(*old_ptr != '%') {
*new_ptr++ = *old_ptr++;
continue;
} else {
*new_ptr++ = '|'; /* delimier to make it readable */
*new_ptr++ = *old_ptr++;
while( *old_ptr == 'L' || *old_ptr == 'l'
|| isdigit(*old_ptr) ) {
*new_ptr++ = *old_ptr++;
}
if( *old_ptr == 'b') {
if(isdigit(*(old_ptr-1))) {
if(*(old_ptr-1) == '1' ||
*(old_ptr-1) == '2' ||
*(old_ptr-1) == '3' ||
*(old_ptr-1) == '4') {
new_ptr--;
} else if(*(old_ptr-1) == '8') {
*--new_ptr='l';
*++new_ptr='l';
new_ptr++;
}
}
*new_ptr++ = 'd';
old_ptr++;
}
else if ( *old_ptr == 's') {
if(isdigit(*(old_ptr-1)) && *(old_ptr-1)=='0')
new_ptr--;
*new_ptr++ = 's';
old_ptr++;
} else
*new_ptr++ = *old_ptr++;
}
}
*new_ptr=0;
}
/* trace data in ASCII format
Format of the common prefix of the trace data:
groupid|subhookid|sec|usec|tgid|ppid|pid|cpuid|
*/
#if defined(ASCII_TRACE)
#define _lket_trace(GroupID, hookID, fmt, args...) do { \
struct timeval tv; \
do_gettimeofday (&tv); \
fmt_change(fmt, new_sysfmt, NEW_SYSFMT_START); \
_stp_printf(new_sysfmt, \
(_FMT_)GroupID, (_FMT_)hookID, (_FMT_)tv.tv_sec, (_FMT_)tv.tv_usec,\
(_FMT_)current->tgid, (_FMT_)current->parent->pid,\
(_FMT_)current->pid, (_FMT_)current->thread_info->cpu, args);\
} while(0)
#define _lket_trace_extra(fmt, args...) do {\
fmt_change(fmt, new_userfmt, NEW_USERFMT_START);\
_stp_printf(new_userfmt, args);\
} while(0)
#else //binary trace
static inline int this_event_len(void)
{
return 0;
}
/* we use 2 bytes to store the length. */
#define _lket_trace(GroupID, hookID, fmt, args...) do { \
struct timeval tv; \
do_gettimeofday (&tv); \
_stp_printf("%1b%2n%1b%1b%4b%4b%4b%4b%4b%1b"fmt, \
(_FMT_)LKET_PKT_SYS, (_FMT_)GroupID, (_FMT_)hookID, \
(_FMT_)tv.tv_sec, (_FMT_)tv.tv_usec, (_FMT_)current->tgid, \
(_FMT_)current->parent->pid, (_FMT_)current->pid, \
(_FMT_)current->thread_info->cpu, args);\
} while(0)
#define _lket_trace_extra(fmt, args...) do {\
_stp_printf("%1b%2n%0s"fmt, (_FMT_)LKET_PKT_USER, fmt, args);\
} while(0)
#endif
#endif
%}
function lket_backtrace () %{
if (CONTEXT->regs) {
String str = _stp_string_init (0);
_stp_stack_sprint (str, CONTEXT->regs, 0);
#if defined(ASCII_TRACE)
_stp_printf("|BACKTRACE: %s", _stp_string_ptr(str));
#else
_stp_printf("%1b%2n%0s", (_FMT_)LKET_PKT_BT, _stp_string_ptr(str));
#endif
}
%}
|