]>
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 | ||
c1008fd0 SC |
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 | ||
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 SC |
39 | def semaphore_def_append(self, this_probe): |
40 | self.semaphores_def += "__extension__ long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe) | |
41 | def semaphore_def_write(self, file): | |
42 | file.write(self.semaphores_def) | |
5111fc3e | 43 | def generate(self, provider, header, add_typedefs): |
c1008fd0 SC |
44 | have_provider = False |
45 | self.f = open(provider) | |
46 | self.h = open(header,mode='w') | |
2a22df62 | 47 | self.h.write("/* Generated by the Systemtap dtrace wrapper */\n") |
4f46087f | 48 | self.h.write("\n#define STAP_HAS_SEMAPHORES 1\n\n") |
c1008fd0 SC |
49 | self.h.write("\n#include <sys/sdt.h>\n\n") |
50 | in_comment = False | |
5111fc3e | 51 | typedefs = "" |
c1008fd0 SC |
52 | while (True): |
53 | line = self.f.readline() | |
54 | if (line == ""): | |
55 | break | |
5111fc3e | 56 | if (line.find("/*") != -1): |
c1008fd0 | 57 | in_comment = True |
5111fc3e | 58 | if (line.find("*/") != -1): |
c1008fd0 SC |
59 | in_comment = False |
60 | continue | |
61 | if (in_comment): | |
62 | continue | |
5111fc3e | 63 | if (line.find("provider") != -1): |
c1008fd0 SC |
64 | tokens = line.split() |
65 | have_provider = True | |
66 | self.provider = tokens[1] | |
5111fc3e SC |
67 | elif (not have_provider): |
68 | if (add_typedefs): | |
69 | self.h.write (line) | |
70 | elif (have_provider and line.find("probe ") != -1): | |
c1008fd0 SC |
71 | while (line.find(")") < 0): |
72 | line += self.f.readline() | |
73 | this_probe = line[line.find("probe ")+5:line.find("(")].strip() | |
74 | this_probe_canon = self.provider.upper() + "_" + this_probe.replace("__","_").upper() | |
75 | args = (line[line.find("(")+1:line.find(")")]) | |
5111fc3e SC |
76 | args_string = "" |
77 | arg = "" | |
c1008fd0 SC |
78 | i = 0 |
79 | c = 0 | |
4f46087f | 80 | self.semaphore_def_append (this_probe) |
c1008fd0 SC |
81 | while (i < len(args)): |
82 | if (args[i:i+1] == ","): | |
5111fc3e | 83 | args_string = ('%s %s,' % (args_string, arg.strip())) |
c1008fd0 | 84 | c += 1 |
5111fc3e SC |
85 | typedefs = self.typedef_append (typedefs,this_probe,arg,c) |
86 | arg = "" | |
c1008fd0 | 87 | else: |
5111fc3e | 88 | arg = arg + args[i] |
c1008fd0 | 89 | i += 1 |
5111fc3e SC |
90 | if (i != 0): |
91 | args_string = ('%s %s' % (args_string, arg.strip())) | |
92 | if (len(args_string) == 0): | |
46607641 SC |
93 | c = 0 |
94 | stap_str = "STAP_PROBE(provider,%s" % (this_probe) | |
95 | else: | |
96 | c += 1 | |
5111fc3e | 97 | typedefs = self.typedef_append (typedefs,this_probe,arg,c) |
46607641 | 98 | stap_str = "STAP_PROBE%d(provider,%s" % (c,this_probe) |
4f988cd3 | 99 | define_str = "#define %s(" % (this_probe_canon) |
46607641 | 100 | i = 1 |
4f988cd3 | 101 | while (i <= c): |
2a22df62 | 102 | if (i != 1): |
4f988cd3 | 103 | define_str += "," |
46607641 SC |
104 | define_str = define_str + "arg%s" % (i); |
105 | stap_str = stap_str + ",arg%s" % (i); | |
4f988cd3 | 106 | i += 1 |
5111fc3e | 107 | self.h.write ('/* %s (%s) */\n' % (this_probe_canon,args_string)) |
4f46087f SC |
108 | self.h.write ('#define %s_ENABLED() %s_semaphore\n' % (this_probe_canon,this_probe)) |
109 | self.h.write ("__extension__ extern long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe)) | |
46607641 | 110 | self.h.write (define_str + ") \\\n") |
4f988cd3 | 111 | self.h.write (stap_str + ")\n\n") |
5111fc3e SC |
112 | elif (line.find("}") != -1 and have_provider): |
113 | have_provider = False | |
114 | if (add_typedefs): | |
115 | self.h.write (typedefs) | |
116 | self.h.close() | |
117 | ||
c1008fd0 | 118 | |
c1008fd0 | 119 | def usage (): |
5111fc3e SC |
120 | print "Usage " + sys.argv[0] + " [--help] [-h | -G] -s File.d [-o File]" |
121 | ||
122 | def help (): | |
123 | usage() | |
124 | print "Where -h builds a systemtap header file from the .d file" | |
125 | print " -o specifies an explicit output file name," | |
126 | print " The default for -G is file.o and -h is file.h" | |
127 | print " -s specifies the name of the .d input file" | |
128 | print " -G builds a stub file.o from file.d," | |
129 | print " which is required by some packages that use dtrace." | |
c1008fd0 SC |
130 | sys.exit(1) |
131 | ||
132 | def open_file (arg): | |
133 | if (len (sys.argv) <= arg): | |
134 | return False | |
135 | try: | |
136 | file = open(sys.argv[arg], 'r') | |
137 | except IOError: | |
138 | print (sys.argv[arg] + " not found") | |
139 | sys.exit(1) | |
140 | return file | |
141 | ||
4f988cd3 SC |
142 | |
143 | ######################################################################## | |
144 | # main | |
145 | ######################################################################## | |
146 | ||
c1008fd0 SC |
147 | if (len (sys.argv) < 2): |
148 | usage() | |
5111fc3e | 149 | sys.exit(1) |
c1008fd0 SC |
150 | |
151 | i = 1 | |
152 | build_header = False | |
153 | build_source = False | |
5111fc3e | 154 | add_typedefs = False |
dd66ed3f | 155 | use_cpp = False |
8bab68f6 | 156 | h_ext = '.h' |
c1008fd0 SC |
157 | filename = "" |
158 | while (i < len (sys.argv)): | |
159 | if (sys.argv[i] == "-o"): | |
160 | i += 1 | |
161 | filename = sys.argv[i] | |
162 | elif (sys.argv[i] == "-s"): | |
163 | i += 1 | |
164 | s_filename = sys.argv[i] | |
dd66ed3f SC |
165 | elif (sys.argv[i] == "-C"): |
166 | use_cpp = True | |
c1008fd0 SC |
167 | elif (sys.argv[i] == "-h"): |
168 | build_header = True | |
169 | elif (sys.argv[i] == "-G"): | |
170 | build_source = True | |
5111fc3e SC |
171 | elif (sys.argv[i] == "--types"): |
172 | add_typedefs = True | |
173 | elif (sys.argv[i] == "--help"): | |
174 | help() | |
c1008fd0 | 175 | i += 1 |
c1008fd0 SC |
176 | if (build_header == False and build_source == False): |
177 | usage() | |
178 | sys.exit(1) | |
179 | ||
dd66ed3f SC |
180 | if (s_filename != "" and use_cpp): |
181 | (d,fn) = mkstemp(suffix=".d") | |
182 | retcode = call(["cpp", s_filename, fn]) | |
183 | if (retcode != 0): | |
184 | print "\"cpp s_filename\" failed" | |
185 | usage() | |
186 | sys.exit(1) | |
187 | s_filename = fn | |
c1008fd0 SC |
188 | if (filename == ""): |
189 | if (s_filename != ""): | |
bf611ccc | 190 | (filename,ext) = os.path.splitext(s_filename) |
3a45db13 | 191 | filename = os.path.basename(filename) |
c1008fd0 SC |
192 | else: |
193 | usage | |
194 | sys.exit(1) | |
b4b70fe3 | 195 | else: |
8bab68f6 SC |
196 | if (build_header): |
197 | h_ext = "" | |
198 | else: | |
199 | (filename,ext) = os.path.splitext(filename) | |
c1008fd0 SC |
200 | if (build_header): |
201 | providers = provider() | |
8bab68f6 SC |
202 | providers.generate(s_filename, filename + h_ext, add_typedefs) |
203 | elif (build_source): | |
bf611ccc | 204 | (basename,ext) = os.path.splitext(s_filename) |
4f46087f SC |
205 | |
206 | # create for semaphore_def_write | |
207 | providers = provider() | |
208 | (d,fn) = mkstemp(suffix=".h") | |
209 | providers.generate(s_filename, fn, add_typedefs) | |
210 | os.remove(fn) | |
211 | ||
48930434 | 212 | (d,fn) = mkstemp(suffix=".c") |
c1008fd0 | 213 | f = open(fn,mode='w') |
8bab68f6 | 214 | f.write("static __dtrace () {}\n") |
4f46087f | 215 | providers.semaphore_def_write(f) |
c1008fd0 | 216 | f.close() |
e4c3091f | 217 | call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"], shell=False) |
c1008fd0 | 218 | os.remove(fn) |
dd66ed3f SC |
219 | if (use_cpp): |
220 | os.remove(s_filename) |