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