]>
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: | |
5111fc3e SC |
20 | def typedef_append(self, typedefs,this_probe,arg,c): |
21 | if (add_typedefs): | |
22 | split_arg = arg.rsplit(None,1) | |
23 | type_name = " %s_arg%d" % (this_probe.replace("__","_"),c) | |
24 | if (len(split_arg) > 1): | |
25 | typedefs += ("typedef " + arg.replace(" " + split_arg[1].split("[")[0].lstrip("*"),type_name).strip() + "; ") | |
26 | typedefs += (type_name + type_name + "_v;\n") | |
27 | else: | |
28 | typedefs += ("typedef " + arg.strip() + type_name + "; ") | |
29 | typedefs += (type_name + type_name + "_v;\n") | |
30 | return typedefs | |
31 | def generate(self, provider, header, add_typedefs): | |
c1008fd0 SC |
32 | have_provider = False |
33 | self.f = open(provider) | |
34 | self.h = open(header,mode='w') | |
2a22df62 | 35 | self.h.write("/* Generated by the Systemtap dtrace wrapper */\n") |
c1008fd0 SC |
36 | self.h.write("\n#include <sys/sdt.h>\n\n") |
37 | in_comment = False | |
5111fc3e | 38 | typedefs = "" |
c1008fd0 SC |
39 | while (True): |
40 | line = self.f.readline() | |
41 | if (line == ""): | |
42 | break | |
5111fc3e | 43 | if (line.find("/*") != -1): |
c1008fd0 | 44 | in_comment = True |
5111fc3e | 45 | if (line.find("*/") != -1): |
c1008fd0 SC |
46 | in_comment = False |
47 | continue | |
48 | if (in_comment): | |
49 | continue | |
5111fc3e | 50 | if (line.find("provider") != -1): |
c1008fd0 SC |
51 | tokens = line.split() |
52 | have_provider = True | |
53 | self.provider = tokens[1] | |
5111fc3e SC |
54 | elif (not have_provider): |
55 | if (add_typedefs): | |
56 | self.h.write (line) | |
57 | elif (have_provider and line.find("probe ") != -1): | |
c1008fd0 SC |
58 | while (line.find(")") < 0): |
59 | line += self.f.readline() | |
60 | this_probe = line[line.find("probe ")+5:line.find("(")].strip() | |
61 | this_probe_canon = self.provider.upper() + "_" + this_probe.replace("__","_").upper() | |
62 | args = (line[line.find("(")+1:line.find(")")]) | |
5111fc3e SC |
63 | args_string = "" |
64 | arg = "" | |
c1008fd0 SC |
65 | i = 0 |
66 | c = 0 | |
c1008fd0 SC |
67 | while (i < len(args)): |
68 | if (args[i:i+1] == ","): | |
5111fc3e | 69 | args_string = ('%s %s,' % (args_string, arg.strip())) |
c1008fd0 | 70 | c += 1 |
5111fc3e SC |
71 | typedefs = self.typedef_append (typedefs,this_probe,arg,c) |
72 | arg = "" | |
c1008fd0 | 73 | else: |
5111fc3e | 74 | arg = arg + args[i] |
c1008fd0 | 75 | i += 1 |
5111fc3e SC |
76 | if (i != 0): |
77 | args_string = ('%s %s' % (args_string, arg.strip())) | |
78 | if (len(args_string) == 0): | |
46607641 SC |
79 | c = 0 |
80 | stap_str = "STAP_PROBE(provider,%s" % (this_probe) | |
81 | else: | |
82 | c += 1 | |
5111fc3e | 83 | typedefs = self.typedef_append (typedefs,this_probe,arg,c) |
46607641 | 84 | stap_str = "STAP_PROBE%d(provider,%s" % (c,this_probe) |
4f988cd3 | 85 | define_str = "#define %s(" % (this_probe_canon) |
46607641 | 86 | i = 1 |
4f988cd3 | 87 | while (i <= c): |
2a22df62 | 88 | if (i != 1): |
4f988cd3 | 89 | define_str += "," |
46607641 SC |
90 | define_str = define_str + "arg%s" % (i); |
91 | stap_str = stap_str + ",arg%s" % (i); | |
4f988cd3 | 92 | i += 1 |
5111fc3e | 93 | self.h.write ('/* %s (%s) */\n' % (this_probe_canon,args_string)) |
c1008fd0 | 94 | self.h.write ('#define %s_ENABLED() 1\n' % this_probe_canon) |
46607641 | 95 | self.h.write (define_str + ") \\\n") |
4f988cd3 | 96 | self.h.write (stap_str + ")\n\n") |
5111fc3e SC |
97 | elif (line.find("}") != -1 and have_provider): |
98 | have_provider = False | |
99 | if (add_typedefs): | |
100 | self.h.write (typedefs) | |
101 | self.h.close() | |
102 | ||
c1008fd0 | 103 | |
c1008fd0 | 104 | def usage (): |
5111fc3e SC |
105 | print "Usage " + sys.argv[0] + " [--help] [-h | -G] -s File.d [-o File]" |
106 | ||
107 | def help (): | |
108 | usage() | |
109 | print "Where -h builds a systemtap header file from the .d file" | |
110 | print " -o specifies an explicit output file name," | |
111 | print " The default for -G is file.o and -h is file.h" | |
112 | print " -s specifies the name of the .d input file" | |
113 | print " -G builds a stub file.o from file.d," | |
114 | print " which is required by some packages that use dtrace." | |
c1008fd0 SC |
115 | sys.exit(1) |
116 | ||
117 | def open_file (arg): | |
118 | if (len (sys.argv) <= arg): | |
119 | return False | |
120 | try: | |
121 | file = open(sys.argv[arg], 'r') | |
122 | except IOError: | |
123 | print (sys.argv[arg] + " not found") | |
124 | sys.exit(1) | |
125 | return file | |
126 | ||
4f988cd3 SC |
127 | |
128 | ######################################################################## | |
129 | # main | |
130 | ######################################################################## | |
131 | ||
c1008fd0 SC |
132 | if (len (sys.argv) < 2): |
133 | usage() | |
5111fc3e | 134 | sys.exit(1) |
c1008fd0 SC |
135 | |
136 | i = 1 | |
137 | build_header = False | |
138 | build_source = False | |
5111fc3e | 139 | add_typedefs = False |
c1008fd0 SC |
140 | filename = "" |
141 | while (i < len (sys.argv)): | |
142 | if (sys.argv[i] == "-o"): | |
143 | i += 1 | |
144 | filename = sys.argv[i] | |
145 | elif (sys.argv[i] == "-s"): | |
146 | i += 1 | |
147 | s_filename = sys.argv[i] | |
148 | elif (sys.argv[i] == "-h"): | |
149 | build_header = True | |
150 | elif (sys.argv[i] == "-G"): | |
5111fc3e | 151 | build_header = True |
c1008fd0 | 152 | build_source = True |
5111fc3e SC |
153 | elif (sys.argv[i] == "--types"): |
154 | add_typedefs = True | |
155 | elif (sys.argv[i] == "--help"): | |
156 | help() | |
c1008fd0 | 157 | i += 1 |
c1008fd0 SC |
158 | if (build_header == False and build_source == False): |
159 | usage() | |
160 | sys.exit(1) | |
161 | ||
162 | if (filename == ""): | |
163 | if (s_filename != ""): | |
bf611ccc | 164 | (filename,ext) = os.path.splitext(s_filename) |
59b2ec52 | 165 | filename = os.path.basename(filename) |
c1008fd0 SC |
166 | else: |
167 | usage | |
168 | sys.exit(1) | |
b4b70fe3 SC |
169 | else: |
170 | (filename,ext) = os.path.splitext(filename) | |
c1008fd0 SC |
171 | |
172 | if (build_header): | |
173 | providers = provider() | |
5111fc3e SC |
174 | providers.generate(s_filename, filename + ".h", add_typedefs) |
175 | if (build_source): | |
bf611ccc MW |
176 | (basename,ext) = os.path.splitext(s_filename) |
177 | basename = os.path.basename(basename) | |
e3c5bcd9 | 178 | (d,fn) = mkstemp(suffix=".c",prefix=basename) |
c1008fd0 | 179 | f = open(fn,mode='w') |
5111fc3e | 180 | f.write("#include \"" + filename + ".h\"\nstatic __dtrace () {}\n") |
c1008fd0 | 181 | f.close() |
e4aaabda | 182 | call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", filename + ".o"], shell=False) |
c1008fd0 | 183 | os.remove(fn) |