]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/bash | |
2 | ||
3 | # $1 - install/uninstall | |
4 | # $2 - PID/unique name | |
5 | # $3 - RULE name | |
6 | # $4 - class | |
7 | # $5 - method | |
8 | # $6 - number of args | |
9 | # $7 - entry/exit/line | |
10 | # $8 - backtrace trigger | |
11 | ||
12 | exec 1>&2 # redirect byteman/etc. tracing output to stderr, for easier filtering | |
13 | ||
14 | if [[ $# -gt 8 || $# -lt 7 ]]; then | |
15 | echo "need seven or eight arguments" | |
16 | exit 1 | |
17 | fi | |
18 | ||
19 | arg_command=$1 | |
20 | # resolve the overloaded parameter; PR21020 | |
21 | if [ $arg_command = "install31" ]; then | |
22 | mode=install | |
23 | stap="31" | |
24 | elif [ $arg_command = "uninstall31" ]; then | |
25 | mode=uninstall | |
26 | stap="31" | |
27 | elif [ $arg_command = "install" ]; then | |
28 | mode=install | |
29 | stap="" | |
30 | elif [ $arg_command = "uninstall" ]; then | |
31 | mode=uninstall | |
32 | else | |
33 | exit 1 | |
34 | fi | |
35 | arg_jvmpid=$2 | |
36 | arg_rulename=$3 | |
37 | arg_class=$4 | |
38 | arg_method=$5 | |
39 | arg_argcount=$6 | |
40 | arg_probetype=$7 | |
41 | ||
42 | if [ $# -eq 7 ]; then | |
43 | arg_backtrace=0 | |
44 | else | |
45 | arg_backtrace=$8 | |
46 | fi | |
47 | ||
48 | SYSTEMTAP_DIR=${SYSTEMTAP_DIR-$HOME/.systemtap} | |
49 | BYTEMAN_HOME=${BYTEMAN_HOME-/usr/share/java/byteman} | |
50 | JAVA_HOME=${JAVA_HOME-/usr/lib/jvm/java} | |
51 | BYTEMAN_INSTALL_OPTS=${BYTEMAN_INSTALL_OPTS--Dorg.jboss.byteman.transform.all=true} | |
52 | SYSTEMTAP_VERBOSE=${SYSTEMTAP_VERBOSE-0} | |
53 | ||
54 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then | |
55 | BYTEMAN_INSTALL_OPTS="$BYTEMAN_INSTALL_OPTS -Dorg.jboss.byteman.verbose" | |
56 | set -x | |
57 | else | |
58 | exec >/dev/null | |
59 | # NB: preserve stderr | |
60 | fi | |
61 | ||
62 | prefix=@prefix@ | |
63 | exec_prefix=@exec_prefix@ | |
64 | pkglibexecdir=@pkglibexecdir@ | |
65 | ||
66 | HELPERSDT_JAR=${pkglibexecdir}/HelperSDT.jar | |
67 | if [ ! -f ${HELPERSDT_JAR} ]; then | |
68 | exec 1>&2 | |
69 | echo "Missing $HELPERSDT_JAR" | |
70 | exit 1 | |
71 | fi | |
72 | ||
73 | flagdir="$SYSTEMTAP_DIR/java" | |
74 | mkdir -p $flagdir | |
75 | ||
76 | # Find our target jvm pid. Due to the possibility of our | |
77 | # target jvm pid being passed as a string, we need to allow | |
78 | # for the possiblity that more than one pid may match the | |
79 | # target jvm pid. If this is the case, we need to have a | |
80 | # nested call to stapbm with the actual pid of the jvm pid | |
81 | ||
82 | if ! [[ $arg_jvmpid =~ ^[0-9]+$ ]]; then | |
83 | target_pid=`jps -l | grep $arg_jvmpid | cut -f1 -d" "` | |
84 | for target in $target_pid; do | |
85 | $0 "$arg_command" "$target" "$arg_rulename" "$arg_class" "$arg_method" "$arg_argcount" "$arg_probetype" "$arg_backtrace" | |
86 | done | |
87 | exit 0 | |
88 | else | |
89 | target_pid=$arg_jvmpid | |
90 | fi | |
91 | ||
92 | # Our target jvm may not have the byteman agent installed yet. Let's do | |
93 | # that first. We use a signal file in $flagdir to show that the | |
94 | # JVM is ready for further bytemanning without a prior setup step, | |
95 | # and include in it the designated byteman agent listening-port number. | |
96 | # | |
97 | byteman_installed_portfile=$flagdir/`hostname`-${target_pid}-bm | |
98 | ||
99 | exec 200>>$byteman_installed_portfile # open/create lock file | |
100 | flock -x 200 # exclusive-lock it | |
101 | ||
102 | if [ -s $byteman_installed_portfile ]; then | |
103 | bmport=`cat $byteman_installed_portfile` | |
104 | ||
105 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then | |
106 | echo "Byteman agent reused for java pid $target_pid, port $bmport" | |
107 | fi | |
108 | ||
109 | # XXX: liveness-check the port; bmsubmit with no argument just lists current rules | |
110 | # if fails, delete the _portfile and retry everything | |
111 | else | |
112 | # bmport=9091 | |
113 | bmport=`expr 9090 + $RANDOM % 10000` | |
114 | existing=`ss -atn | awk '{print $4}' | grep ':'$bmport'$'` | |
115 | if [ "x$existing" != "x" ]; then | |
116 | echo "Byteman port $bmport already in use, retrying." | |
117 | exec "$@" | |
118 | fi | |
119 | ||
120 | # There are two ways to invoke and run byteman operations with the jvm's we're interested | |
121 | # in, we can alter the startup arguments to include a -javaagent parameter, or use | |
122 | # byteman and its use of VMAttach libraries, for our case it always makes sense to use | |
123 | # byteman classes directly and avoid -javaagent | |
124 | ||
125 | bminstall -b -p $bmport $BYTEMAN_INSTALL_OPTS $target_pid | |
126 | if [ $? -ne 0 ]; then | |
127 | echo "Byteman agent failed to install for java pid $target_pid, port $bmport" | |
128 | exit 1 | |
129 | fi | |
130 | bmsubmit -p $bmport -s $HELPERSDT_JAR | |
131 | if [ $? -ne 0 ]; then | |
132 | echo "Byteman agent failed to load HelperSDT.jar java pid $target_pid, port $bmport" | |
133 | exit 1 | |
134 | fi | |
135 | ||
136 | echo $bmport > $byteman_installed_portfile | |
137 | ||
138 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then | |
139 | echo "Byteman agent installed for java pid $target_pid, port $bmport" | |
140 | fi | |
141 | # XXX: Erase file to keep it from sticking around indefinitely, | |
142 | # in case process ends, machine reboots, pid gets reused | |
143 | # XXX: consider explicit notification to stapbm via process("java").begin/end ? | |
144 | # ... or else: liveness-check below | |
145 | fi | |
146 | exec 200>&- # close file & release flock | |
147 | ||
148 | ||
149 | function echo_bytemanrule() | |
150 | { | |
151 | echo "RULE $arg_rulename" | |
152 | echo "CLASS $arg_class" | |
153 | echo "METHOD $arg_method" | |
154 | echo "HELPER org.systemtap.byteman.helper.HelperSDT" | |
155 | case "$arg_probetype" in | |
156 | entry) | |
157 | echo "AT ENTRY" | |
158 | ;; | |
159 | exi*) | |
160 | echo "AT RETURN" | |
161 | ;; | |
162 | *) | |
163 | echo "AT LINE $arg_probetype" | |
164 | ;; | |
165 | esac | |
166 | echo "IF TRUE" | |
167 | if [ "$arg_backtrace" == "1" ]; then | |
168 | echo 'DO STAP_BACKTRACE("'$arg_rulename'");' | |
169 | else | |
170 | echo -n 'DO ' | |
171 | fi | |
172 | case "$arg_argcount" in | |
173 | # For PR21010, we invoke another java<->stap ABI | |
174 | 0) echo -n 'METHOD_STAP'$stap'_PROBE0("'$arg_rulename'")' ;; | |
175 | 1) echo -n 'METHOD_STAP'$stap'_PROBE1("'$arg_rulename'", $1)' ;; | |
176 | 2) echo -n 'METHOD_STAP'$stap'_PROBE2("'$arg_rulename'", $1, $2)' ;; | |
177 | 3) echo -n 'METHOD_STAP'$stap'_PROBE3("'$arg_rulename'", $1, $2, $3)' ;; | |
178 | 4) echo -n 'METHOD_STAP'$stap'_PROBE4("'$arg_rulename'", $1, $2, $3, $4)' ;; | |
179 | 5) echo -n 'METHOD_STAP'$stap'_PROBE5("'$arg_rulename'", $1, $2, $3, $4, $5)' ;; | |
180 | 6) echo -n 'METHOD_STAP'$stap'_PROBE6("'$arg_rulename'", $1, $2, $3, $4, $5, $6)' ;; | |
181 | 7) echo -n 'METHOD_STAP'$stap'_PROBE7("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7)' ;; | |
182 | 8) echo -n 'METHOD_STAP'$stap'_PROBE8("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7, $8)' ;; | |
183 | 9) echo -n 'METHOD_STAP'$stap'_PROBE9("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7, $8, $9)' ;; | |
184 | 10) echo -n 'METHOD_STAP'$stap'_PROBE10("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10)' ;; | |
185 | *) echo 'bad arg-count'; exit 1 ;; | |
186 | esac | |
187 | if [ "$arg_backtrace" == "1" ]; then | |
188 | echo ';' | |
189 | echo 'METHOD_BT_DELETE("'$arg_rulename'")' | |
190 | else | |
191 | echo '' | |
192 | fi | |
193 | echo "ENDRULE" | |
194 | } | |
195 | ||
196 | ||
197 | # Generate the byteman rule file on-the-fly | |
198 | btmfile=$flagdir/`hostname`-$$.btm | |
199 | echo_bytemanrule > $btmfile | |
200 | trap 'rm -f $btmfile' 0 1 2 3 4 5 9 15 | |
201 | ||
202 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then | |
203 | echo "Byteman rule file:" | |
204 | cat $btmfile | |
205 | fi | |
206 | ||
207 | if [ $mode = "uninstall" ]; then | |
208 | bmcmd=-u | |
209 | else | |
210 | bmcmd=-l | |
211 | fi | |
212 | ||
213 | bmsubmit -p $bmport $bmcmd $btmfile |