]>
Commit | Line | Data |
---|---|---|
c1008fd0 SC |
1 | #!/usr/bin/python |
2 | ||
3 | # This handles the systemtap equivalent of | |
d294a649 | 4 | # $(DTRACE) $(DTRACEFLAGS) -G -s $^ -o $@ |
c1008fd0 | 5 | # $(DTRACE) $(DTRACEFLAGS) -h -s $^ -o $@ |
d294a649 SC |
6 | # which is a step that builds DTrace provider and probe definitions |
7 | ||
278c9759 | 8 | # Copyright (C) 2009, 2010 Red Hat Inc. |
c1008fd0 SC |
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 | ||
5111fc3e | 15 | import os,posix,string,sys |
c0d0d868 | 16 | from subprocess import call |
e3c5bcd9 | 17 | from tempfile import mkstemp |
c1008fd0 SC |
18 | |
19 | class provider: | |
4f46087f SC |
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) | |
5111fc3e SC |
26 | def typedef_append(self, typedefs,this_probe,arg,c): |
27 | if (add_typedefs): | |
28 | split_arg = arg.rsplit(None,1) | |
4f46087f SC |
29 | if (self.basic_type(arg)): |
30 | return typedefs | |
5111fc3e SC |
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 | |
4f46087f | 39 | def semaphore_def_append(self, this_probe): |
8faa1fc5 | 40 | # NB: unsigned short is fixed in ABI |
278c9759 | 41 | self.semaphores_def += '#if defined STAP_SDT_V1 || ! defined STAP_SDT_V2\n' |
a794dbeb FCE |
42 | self.semaphores_def += '#define %s_%s_semaphore %s_semaphore\n' % (self.provider,this_probe,this_probe) |
43 | self.semaphores_def += '#endif\n' | |
44 | self.semaphores_def += "__extension__ unsigned short %s_%s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (self.provider,this_probe) | |
4f46087f SC |
45 | def semaphore_def_write(self, file): |
46 | file.write(self.semaphores_def) | |
5111fc3e | 47 | def generate(self, provider, header, add_typedefs): |
c1008fd0 SC |
48 | have_provider = False |
49 | self.f = open(provider) | |
50 | self.h = open(header,mode='w') | |
2a22df62 | 51 | self.h.write("/* Generated by the Systemtap dtrace wrapper */\n") |
63b4fd14 | 52 | self.h.write("\n#define STAP_HAS_SEMAPHORES 1\n\n") |
c1008fd0 SC |
53 | self.h.write("\n#include <sys/sdt.h>\n\n") |
54 | in_comment = False | |
5111fc3e | 55 | typedefs = "" |
c1008fd0 SC |
56 | while (True): |
57 | line = self.f.readline() | |
58 | if (line == ""): | |
59 | break | |
5111fc3e | 60 | if (line.find("/*") != -1): |
c1008fd0 | 61 | in_comment = True |
5111fc3e | 62 | if (line.find("*/") != -1): |
c1008fd0 SC |
63 | in_comment = False |
64 | continue | |
65 | if (in_comment): | |
66 | continue | |
5111fc3e | 67 | if (line.find("provider") != -1): |
c1008fd0 SC |
68 | tokens = line.split() |
69 | have_provider = True | |
70 | self.provider = tokens[1] | |
5111fc3e SC |
71 | elif (not have_provider): |
72 | if (add_typedefs): | |
73 | self.h.write (line) | |
74 | elif (have_provider and line.find("probe ") != -1): | |
c1008fd0 SC |
75 | while (line.find(")") < 0): |
76 | line += self.f.readline() | |
77 | this_probe = line[line.find("probe ")+5:line.find("(")].strip() | |
78 | this_probe_canon = self.provider.upper() + "_" + this_probe.replace("__","_").upper() | |
79 | args = (line[line.find("(")+1:line.find(")")]) | |
5111fc3e SC |
80 | args_string = "" |
81 | arg = "" | |
c1008fd0 SC |
82 | i = 0 |
83 | c = 0 | |
4f46087f | 84 | self.semaphore_def_append (this_probe) |
c1008fd0 SC |
85 | while (i < len(args)): |
86 | if (args[i:i+1] == ","): | |
5111fc3e | 87 | args_string = ('%s %s,' % (args_string, arg.strip())) |
c1008fd0 | 88 | c += 1 |
5111fc3e SC |
89 | typedefs = self.typedef_append (typedefs,this_probe,arg,c) |
90 | arg = "" | |
c1008fd0 | 91 | else: |
5111fc3e | 92 | arg = arg + args[i] |
c1008fd0 | 93 | i += 1 |
5111fc3e SC |
94 | if (i != 0): |
95 | args_string = ('%s %s' % (args_string, arg.strip())) | |
96 | if (len(args_string) == 0): | |
46607641 | 97 | c = 0 |
a794dbeb | 98 | stap_str = "STAP_PROBE(%s,%s" % (self.provider,this_probe) |
46607641 SC |
99 | else: |
100 | c += 1 | |
5111fc3e | 101 | typedefs = self.typedef_append (typedefs,this_probe,arg,c) |
a794dbeb | 102 | stap_str = "STAP_PROBE%d(%s,%s" % (c,self.provider,this_probe) |
4f988cd3 | 103 | define_str = "#define %s(" % (this_probe_canon) |
46607641 | 104 | i = 1 |
4f988cd3 | 105 | while (i <= c): |
2a22df62 | 106 | if (i != 1): |
4f988cd3 | 107 | define_str += "," |
46607641 SC |
108 | define_str = define_str + "arg%s" % (i); |
109 | stap_str = stap_str + ",arg%s" % (i); | |
4f988cd3 | 110 | i += 1 |
5111fc3e | 111 | self.h.write ('/* %s (%s) */\n' % (this_probe_canon,args_string)) |
f10d1268 | 112 | # XXX Enable this when .so semaphores work properly |
278c9759 | 113 | self.h.write ('#if defined STAP_SDT_V1 || ! defined STAP_SDT_V2\n') |
63b4fd14 | 114 | self.h.write ('#define %s_ENABLED() %s_semaphore\n' % (this_probe_canon,this_probe)) |
a794dbeb | 115 | self.h.write ('#define %s_%s_semaphore %s_semaphore\n' % (self.provider,this_probe,this_probe)) |
278c9759 SC |
116 | self.h.write ('#else\n') |
117 | self.h.write ('#define %s_ENABLED() %s_%s_semaphore\n' % (this_probe_canon,self.provider,this_probe)) | |
a794dbeb | 118 | self.h.write ('#endif\n') |
8faa1fc5 | 119 | # NB: unsigned short is fixed in ABI |
a794dbeb | 120 | self.h.write ("__extension__ extern unsigned short %s_%s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (self.provider,this_probe)) |
46607641 | 121 | self.h.write (define_str + ") \\\n") |
4f988cd3 | 122 | self.h.write (stap_str + ")\n\n") |
5111fc3e SC |
123 | elif (line.find("}") != -1 and have_provider): |
124 | have_provider = False | |
125 | if (add_typedefs): | |
126 | self.h.write (typedefs) | |
127 | self.h.close() | |
128 | ||
c1008fd0 | 129 | |
c1008fd0 | 130 | def usage (): |
2d971c6b | 131 | print "Usage " + sys.argv[0] + " [--help] [-h | -G] [-C [-I<Path>]] -s File.d [-o <File>]" |
5111fc3e SC |
132 | |
133 | def help (): | |
134 | usage() | |
135 | print "Where -h builds a systemtap header file from the .d file" | |
2d971c6b | 136 | print " -C when used with -h, also run cpp preprocessor" |
5111fc3e | 137 | print " -o specifies an explicit output file name," |
2d971c6b MW |
138 | print " the default for -G is file.o and -h is file.h" |
139 | print " -I when running cpp pass through this -I include Path" | |
5111fc3e SC |
140 | print " -s specifies the name of the .d input file" |
141 | print " -G builds a stub file.o from file.d," | |
142 | print " which is required by some packages that use dtrace." | |
c1008fd0 SC |
143 | sys.exit(1) |
144 | ||
145 | def open_file (arg): | |
146 | if (len (sys.argv) <= arg): | |
147 | return False | |
148 | try: | |
149 | file = open(sys.argv[arg], 'r') | |
150 | except IOError: | |
151 | print (sys.argv[arg] + " not found") | |
152 | sys.exit(1) | |
153 | return file | |
154 | ||
4f988cd3 SC |
155 | |
156 | ######################################################################## | |
157 | # main | |
158 | ######################################################################## | |
159 | ||
c1008fd0 SC |
160 | if (len (sys.argv) < 2): |
161 | usage() | |
5111fc3e | 162 | sys.exit(1) |
c1008fd0 SC |
163 | |
164 | i = 1 | |
165 | build_header = False | |
166 | build_source = False | |
5111fc3e | 167 | add_typedefs = False |
903b9fcd | 168 | keep_temps = False |
dd66ed3f | 169 | use_cpp = False |
8bab68f6 | 170 | h_ext = '.h' |
c1008fd0 | 171 | filename = "" |
2d971c6b MW |
172 | s_filename = "" |
173 | includes = [] | |
278c9759 | 174 | defines = [] |
c1008fd0 SC |
175 | while (i < len (sys.argv)): |
176 | if (sys.argv[i] == "-o"): | |
177 | i += 1 | |
178 | filename = sys.argv[i] | |
179 | elif (sys.argv[i] == "-s"): | |
180 | i += 1 | |
181 | s_filename = sys.argv[i] | |
dd66ed3f SC |
182 | elif (sys.argv[i] == "-C"): |
183 | use_cpp = True | |
278c9759 SC |
184 | elif (sys.argv[i].startswith("-D")): |
185 | defines.append(sys.argv[i]) | |
c1008fd0 SC |
186 | elif (sys.argv[i] == "-h"): |
187 | build_header = True | |
2d971c6b MW |
188 | elif (sys.argv[i].startswith("-I")): |
189 | includes.append(sys.argv[i]) | |
c1008fd0 SC |
190 | elif (sys.argv[i] == "-G"): |
191 | build_source = True | |
903b9fcd SC |
192 | elif (sys.argv[i] == "-k"): |
193 | keep_temps = True | |
5111fc3e SC |
194 | elif (sys.argv[i] == "--types"): |
195 | add_typedefs = True | |
196 | elif (sys.argv[i] == "--help"): | |
197 | help() | |
c1008fd0 | 198 | i += 1 |
c1008fd0 SC |
199 | if (build_header == False and build_source == False): |
200 | usage() | |
201 | sys.exit(1) | |
202 | ||
dd66ed3f SC |
203 | if (s_filename != "" and use_cpp): |
204 | (d,fn) = mkstemp(suffix=".d") | |
278c9759 | 205 | args = ['cpp'] + includes + defines + [s_filename, fn] |
2d971c6b | 206 | retcode = call(args) |
dd66ed3f | 207 | if (retcode != 0): |
2d971c6b | 208 | print "\"cpp includes s_filename\" failed" |
dd66ed3f SC |
209 | usage() |
210 | sys.exit(1) | |
211 | s_filename = fn | |
c1008fd0 SC |
212 | if (filename == ""): |
213 | if (s_filename != ""): | |
bf611ccc | 214 | (filename,ext) = os.path.splitext(s_filename) |
3a45db13 | 215 | filename = os.path.basename(filename) |
c1008fd0 SC |
216 | else: |
217 | usage | |
218 | sys.exit(1) | |
b4b70fe3 | 219 | else: |
8bab68f6 SC |
220 | if (build_header): |
221 | h_ext = "" | |
222 | else: | |
223 | (filename,ext) = os.path.splitext(filename) | |
c1008fd0 SC |
224 | if (build_header): |
225 | providers = provider() | |
8bab68f6 SC |
226 | providers.generate(s_filename, filename + h_ext, add_typedefs) |
227 | elif (build_source): | |
bf611ccc | 228 | (basename,ext) = os.path.splitext(s_filename) |
4f46087f SC |
229 | |
230 | # create for semaphore_def_write | |
231 | providers = provider() | |
232 | (d,fn) = mkstemp(suffix=".h") | |
233 | providers.generate(s_filename, fn, add_typedefs) | |
903b9fcd SC |
234 | if (not keep_temps): |
235 | os.remove(fn) | |
236 | else: | |
237 | print "header: " + fn | |
4f46087f | 238 | |
48930434 | 239 | (d,fn) = mkstemp(suffix=".c") |
c1008fd0 | 240 | f = open(fn,mode='w') |
8bab68f6 | 241 | f.write("static __dtrace () {}\n") |
4f46087f | 242 | providers.semaphore_def_write(f) |
c1008fd0 | 243 | f.close() |
b275171e | 244 | #print ["gcc", "-fPIC"] + defines + ["-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"] |
278c9759 | 245 | call(["gcc", "-fPIC"] + defines + ["-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"], shell=False) |
903b9fcd SC |
246 | if (not keep_temps): |
247 | os.remove(fn) | |
248 | else: | |
249 | print "source: " + fn | |
dd66ed3f | 250 | if (use_cpp): |
903b9fcd SC |
251 | if (not keep_temps): |
252 | os.remove(s_filename) | |
253 | else: | |
254 | print "cpp: " + s_filename |