Commit | Line | Data |
---|---|---|
eb6adb25 PMF |
1 | #!/bin/bash |
2 | ||
4a7c7161 PMF |
3 | # usttrace by Pierre-Marc Fournier 2009 |
4 | # Distributed under the GPLv2. | |
5 | ||
63f16f2e PMF |
6 | function error() { |
7 | echo "$0: error: $1" 2>/dev/stderr | |
8 | } | |
9 | ||
87d40fcf PMF |
10 | function sighandler() { |
11 | echo "Caught Ctrl-C" | |
12 | if [ -z "$USTDPID" ]; then | |
13 | USTDPID="$(<$pidfilepath)" | |
14 | fi | |
15 | # Tell the daemon to die | |
16 | kill -SIGTERM "$USTDPID" | |
17 | ||
18 | echo "Waiting for ustd to shutdown..." | |
19 | wait "$USTDPID" | |
20 | ||
21 | rm "$pidfilepath" | |
22 | ||
23 | exit 0; | |
24 | } | |
25 | ||
cd814711 | 26 | USTTRACE_DIR="$(dirname $0)" |
6b22d5c1 JB |
27 | if [ -x "${USTTRACE_DIR}/ustd/ustd" ] ; then |
28 | # Use the not installed libraries instead | |
29 | USTD="${USTTRACE_DIR}/ustd/ustd" | |
30 | LIBINTERFORK_PATH="${USTTRACE_DIR}/libinterfork/.libs/libinterfork.so" | |
31 | LIBMALLOCWRAP_PATH="${USTTRACE_DIR}/libmallocwrap/.libs/libmallocwrap.so" | |
32 | LIBUST_PATH="${USTTRACE_DIR}/libust/.libs/libust.so" | |
33 | else | |
34 | # Use the libraries that the dynamic link finds | |
35 | USTD="ustd" | |
63f16f2e PMF |
36 | if [ ! -x "$(which ustd 2>/dev/null)" ]; then |
37 | error "cannot find an executable ustd; make sure its location is in the PATH" | |
38 | exit 1 | |
39 | fi | |
6b22d5c1 JB |
40 | LIBINTERFORK_PATH="libinterfork.so" |
41 | LIBMALLOCWRAP_PATH="libmallocwrap.so" | |
9ccc0699 | 42 | LIBUST_PATH="libust.so.0" |
6b22d5c1 | 43 | fi |
eb6adb25 | 44 | |
cd814711 | 45 | BASE_TRACE_DIR="${HOME}/.usttraces" |
eb6adb25 PMF |
46 | |
47 | function usage () { | |
b13ba584 PMF |
48 | echo "usage: $0 OPTIONS COMMAND" 2>/dev/stderr |
49 | echo "" 2>/dev/stderr | |
50 | echo "Options:" 2>/dev/stderr | |
51 | echo " -l Runtime link with UST library." 2>/dev/stderr | |
52 | echo " (Needed only if program was not linked at compile time with libust.)" 2>/dev/stderr | |
53 | echo " -L Add path to ust libraries to LD_LIBRARY_PATH." 2>/dev/stderr | |
54 | echo " -m Instrument malloc calls." 2>/dev/stderr | |
55 | echo " -f Also trace forked processes." 2>/dev/stderr | |
89a10f62 | 56 | echo " -s Use system-wide daemon instead of creating one for this session." 2>/dev/stderr |
eb6adb25 PMF |
57 | } |
58 | ||
89a10f62 | 59 | while getopts ":hlLmfs" options; do |
b13ba584 PMF |
60 | case $options in |
61 | l) arg_preload_libust=1;; | |
62 | L) arg_ld_std_ust=1;; | |
63 | m) arg_preload_malloc=1;; | |
64 | f) arg_preload_fork=1;; | |
89a10f62 | 65 | s) arg_syswide_daemon=1;; |
b13ba584 PMF |
66 | h) usage; |
67 | exit 0;; | |
2a3fba49 | 68 | \?) usage |
b13ba584 | 69 | exit 1;; |
2a3fba49 | 70 | *) usage |
b13ba584 PMF |
71 | exit 1;; |
72 | esac | |
73 | done | |
74 | shift $(($OPTIND - 1)) | |
75 | ||
eb6adb25 | 76 | # Prepare vars |
6b22d5c1 | 77 | CMD=$* |
eb6adb25 PMF |
78 | |
79 | # Validate input | |
80 | if [ -z "$HOME" ]; | |
81 | then | |
82 | error "no home specified" | |
83 | fi | |
84 | ||
85 | if [ -z "$CMD" ]; | |
86 | then | |
87 | error "no command specified" | |
88 | usage; | |
89 | exit 1 | |
90 | fi | |
91 | ||
92 | # Create directory for trace output | |
93 | DATESTRING="$(hostname)-$(date +%Y%m%d%H%M%S)" | |
94 | OUTDIR="$BASE_TRACE_DIR/$DATESTRING" | |
95 | mkdir -p "$OUTDIR" | |
96 | ||
15588720 PMF |
97 | # Choose ustd socket path |
98 | USTDSOCKPATH="/tmp/ustd-sock-$$" | |
eb6adb25 | 99 | |
89a10f62 PMF |
100 | if [ "$arg_syswide_daemon" != "1" ]; |
101 | then | |
b924c127 | 102 | pidfilepath="/tmp/usttrace-$USER-$(date +%Y%m%d%H%M%S%N)-ustd-pid" |
87d40fcf | 103 | trap "sighandler $pidfilepath" SIGINT |
8232f1db | 104 | mkfifo -m 0600 "$pidfilepath" |
89a10f62 | 105 | # Start daemon |
15588720 | 106 | $USTD --pidfile "$pidfilepath" -s "$USTDSOCKPATH" -o "$OUTDIR" >"$OUTDIR/ustd.log" 2>&1 & |
0f3af9f0 PMF |
107 | # ustd sets up its server socket |
108 | # ustd opens the pidfile, blocks because no one has opened it | |
109 | # we open pidfile | |
110 | # we block reading pidfile | |
111 | # ustd writes to pidfile | |
112 | # ustd closes pidfile | |
113 | # we unblock reading pidfile | |
b924c127 | 114 | USTDPID="$(<$pidfilepath)" |
15588720 | 115 | export UST_DAEMON_SOCKET="$USTDSOCKPATH" |
89a10f62 PMF |
116 | fi |
117 | ||
eb6adb25 | 118 | # Establish the environment for the command |
6b22d5c1 JB |
119 | ( |
120 | export UST_TRACE=1 | |
121 | export UST_AUTOPROBE=1 | |
122 | ||
123 | if [ "$arg_preload_libust" = "1" ]; | |
124 | then | |
125 | if [ -n "${LIBUST_PATH%libust.so}" ] ; then | |
126 | export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${LIBUST_PATH%libust.so}" | |
127 | fi | |
128 | export LD_PRELOAD="$LD_PRELOAD:$LIBUST_PATH" | |
129 | fi | |
130 | ||
131 | if [ "$arg_ld_std_ust" = "1" ]; | |
132 | then | |
133 | if [ -n "$${LIBUST_PATH%libust.so}" ] ; then | |
134 | export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${LIBUST_PATH%libust.so}" | |
135 | fi | |
136 | fi | |
137 | ||
138 | if [ "$arg_preload_malloc" = "1" ]; | |
139 | then | |
140 | export LD_PRELOAD="$LD_PRELOAD:$LIBMALLOCWRAP_PATH" | |
141 | fi | |
142 | ||
143 | if [ "$arg_preload_fork" = "1" ]; | |
144 | then | |
89a10f62 | 145 | export LD_PRELOAD="$LD_PRELOAD:$LIBINTERFORK_PATH" |
6b22d5c1 | 146 | fi |
b13ba584 | 147 | |
eb6adb25 | 148 | # Execute the command |
6b22d5c1 JB |
149 | $CMD 2>&1 |
150 | ) | tee "$OUTDIR/app.log" | |
eb6adb25 PMF |
151 | |
152 | ## Because of the keepalive mechanism, we're sure that by the time | |
153 | ## we get here, the daemon is connected to all the buffers that still exist. | |
154 | ## Therefore we can politely ask it to die when it's done. | |
155 | ||
89a10f62 PMF |
156 | if [ "$arg_syswide_daemon" != "1" ]; |
157 | then | |
158 | # Tell the daemon to die | |
159 | kill -SIGTERM "$USTDPID" | |
160 | ||
161 | echo "Waiting for ustd to shutdown..." | |
524a8072 | 162 | wait "$USTDPID" |
b924c127 PMF |
163 | |
164 | rm "$pidfilepath" | |
89a10f62 | 165 | fi |
eb6adb25 | 166 | |
89a10f62 | 167 | echo "Trace was output in: " $OUTDIR |