]> sourceware.org Git - systemtap.git/blob - dtrace.in
Add testsuite for tcl sdt markers.
[systemtap.git] / dtrace.in
1 #!/usr/bin/python
2
3 # This handles the systemtap equivalent of
4 # $(DTRACE) $(DTRACEFLAGS) -G -s $^ -o $@
5 # $(DTRACE) $(DTRACEFLAGS) -h -s $^ -o $@
6 # which is a step that builds DTrace provider and probe definitions
7
8 # Copyright (C) 2009 Red Hat Inc.
9 #
10 # This file is part of systemtap, and is free software. You can
11 # redistribute it and/or modify it under the terms of the GNU General
12 # Public License (GPL); either version 2, or (at your option) any
13 # later version.
14
15 import os,posix,string,sys
16 from subprocess import call
17 from tempfile import mkstemp
18
19 class provider:
20 semaphores_def = "\n"
21 # is the type a basic scalar type?
22 def basic_type(self, arg):
23 basic_types = [ "int","int*","long","long*","short","short int","unsigned long","char","char*","float","double" ]
24 split_arg = arg.rsplit(None,1)
25 return (split_arg[0].strip() in basic_types) & (arg.find("[") == -1)
26 def typedef_append(self, typedefs,this_probe,arg,c):
27 if (add_typedefs):
28 split_arg = arg.rsplit(None,1)
29 if (self.basic_type(arg)):
30 return typedefs
31 type_name = " %s_arg%d" % (this_probe.replace("__","_"),c)
32 if (len(split_arg) > 1):
33 typedefs += ("typedef " + arg.replace(" " + split_arg[1].split("[")[0].lstrip("*"),type_name).strip() + "; ")
34 typedefs += (type_name + type_name + "_v;\n")
35 else:
36 typedefs += ("typedef " + arg.strip() + type_name + "; ")
37 typedefs += (type_name + type_name + "_v;\n")
38 return typedefs
39 def semaphore_def_append(self, this_probe):
40 # NB: unsigned short is fixed in ABI
41 self.semaphores_def += "__extension__ unsigned short %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe)
42 def semaphore_def_write(self, file):
43 file.write(self.semaphores_def)
44 def generate(self, provider, header, add_typedefs):
45 have_provider = False
46 self.f = open(provider)
47 self.h = open(header,mode='w')
48 self.h.write("/* Generated by the Systemtap dtrace wrapper */\n")
49 self.h.write("\n#define STAP_HAS_SEMAPHORES 1\n\n")
50 self.h.write("\n#include <sys/sdt.h>\n\n")
51 in_comment = False
52 typedefs = ""
53 while (True):
54 line = self.f.readline()
55 if (line == ""):
56 break
57 if (line.find("/*") != -1):
58 in_comment = True
59 if (line.find("*/") != -1):
60 in_comment = False
61 continue
62 if (in_comment):
63 continue
64 if (line.find("provider") != -1):
65 tokens = line.split()
66 have_provider = True
67 self.provider = tokens[1]
68 elif (not have_provider):
69 if (add_typedefs):
70 self.h.write (line)
71 elif (have_provider and line.find("probe ") != -1):
72 while (line.find(")") < 0):
73 line += self.f.readline()
74 this_probe = line[line.find("probe ")+5:line.find("(")].strip()
75 this_probe_canon = self.provider.upper() + "_" + this_probe.replace("__","_").upper()
76 args = (line[line.find("(")+1:line.find(")")])
77 args_string = ""
78 arg = ""
79 i = 0
80 c = 0
81 self.semaphore_def_append (this_probe)
82 while (i < len(args)):
83 if (args[i:i+1] == ","):
84 args_string = ('%s %s,' % (args_string, arg.strip()))
85 c += 1
86 typedefs = self.typedef_append (typedefs,this_probe,arg,c)
87 arg = ""
88 else:
89 arg = arg + args[i]
90 i += 1
91 if (i != 0):
92 args_string = ('%s %s' % (args_string, arg.strip()))
93 if (len(args_string) == 0):
94 c = 0
95 stap_str = "STAP_PROBE(provider,%s" % (this_probe)
96 else:
97 c += 1
98 typedefs = self.typedef_append (typedefs,this_probe,arg,c)
99 stap_str = "STAP_PROBE%d(provider,%s" % (c,this_probe)
100 define_str = "#define %s(" % (this_probe_canon)
101 i = 1
102 while (i <= c):
103 if (i != 1):
104 define_str += ","
105 define_str = define_str + "arg%s" % (i);
106 stap_str = stap_str + ",arg%s" % (i);
107 i += 1
108 self.h.write ('/* %s (%s) */\n' % (this_probe_canon,args_string))
109 # XXX Enable this when .so semaphores work properly
110 self.h.write ('#define %s_ENABLED() 1 /*%s_semaphore*/\n' % (this_probe_canon,this_probe))
111 # NB: unsigned short is fixed in ABI
112 self.h.write ("__extension__ extern unsigned short %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe))
113 self.h.write (define_str + ") \\\n")
114 self.h.write (stap_str + ")\n\n")
115 elif (line.find("}") != -1 and have_provider):
116 have_provider = False
117 if (add_typedefs):
118 self.h.write (typedefs)
119 self.h.close()
120
121
122 def usage ():
123 print "Usage " + sys.argv[0] + " [--help] [-h | -G] -s File.d [-o File]"
124
125 def help ():
126 usage()
127 print "Where -h builds a systemtap header file from the .d file"
128 print " -o specifies an explicit output file name,"
129 print " The default for -G is file.o and -h is file.h"
130 print " -s specifies the name of the .d input file"
131 print " -G builds a stub file.o from file.d,"
132 print " which is required by some packages that use dtrace."
133 sys.exit(1)
134
135 def open_file (arg):
136 if (len (sys.argv) <= arg):
137 return False
138 try:
139 file = open(sys.argv[arg], 'r')
140 except IOError:
141 print (sys.argv[arg] + " not found")
142 sys.exit(1)
143 return file
144
145
146 ########################################################################
147 # main
148 ########################################################################
149
150 if (len (sys.argv) < 2):
151 usage()
152 sys.exit(1)
153
154 i = 1
155 build_header = False
156 build_source = False
157 add_typedefs = False
158 keep_temps = False
159 use_cpp = False
160 h_ext = '.h'
161 filename = ""
162 while (i < len (sys.argv)):
163 if (sys.argv[i] == "-o"):
164 i += 1
165 filename = sys.argv[i]
166 elif (sys.argv[i] == "-s"):
167 i += 1
168 s_filename = sys.argv[i]
169 elif (sys.argv[i] == "-C"):
170 use_cpp = True
171 elif (sys.argv[i] == "-h"):
172 build_header = True
173 elif (sys.argv[i] == "-G"):
174 build_source = True
175 elif (sys.argv[i] == "-k"):
176 keep_temps = True
177 elif (sys.argv[i] == "--types"):
178 add_typedefs = True
179 elif (sys.argv[i] == "--help"):
180 help()
181 i += 1
182 if (build_header == False and build_source == False):
183 usage()
184 sys.exit(1)
185
186 if (s_filename != "" and use_cpp):
187 (d,fn) = mkstemp(suffix=".d")
188 retcode = call(["cpp", s_filename, fn])
189 if (retcode != 0):
190 print "\"cpp s_filename\" failed"
191 usage()
192 sys.exit(1)
193 s_filename = fn
194 if (filename == ""):
195 if (s_filename != ""):
196 (filename,ext) = os.path.splitext(s_filename)
197 filename = os.path.basename(filename)
198 else:
199 usage
200 sys.exit(1)
201 else:
202 if (build_header):
203 h_ext = ""
204 else:
205 (filename,ext) = os.path.splitext(filename)
206 if (build_header):
207 providers = provider()
208 providers.generate(s_filename, filename + h_ext, add_typedefs)
209 elif (build_source):
210 (basename,ext) = os.path.splitext(s_filename)
211
212 # create for semaphore_def_write
213 providers = provider()
214 (d,fn) = mkstemp(suffix=".h")
215 providers.generate(s_filename, fn, add_typedefs)
216 if (not keep_temps):
217 os.remove(fn)
218 else:
219 print "header: " + fn
220
221 (d,fn) = mkstemp(suffix=".c")
222 f = open(fn,mode='w')
223 f.write("static __dtrace () {}\n")
224 providers.semaphore_def_write(f)
225 f.close()
226 call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"], shell=False)
227 if (not keep_temps):
228 os.remove(fn)
229 else:
230 print "source: " + fn
231 if (use_cpp):
232 if (not keep_temps):
233 os.remove(s_filename)
234 else:
235 print "cpp: " + s_filename
This page took 0.097865 seconds and 6 git commands to generate.