1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
#!/bin/sh
# This function just re-writes the timestamp of the strace entries to be
# seconds.usecs since boot. To match the timestamping of ftrace (so we can
# merge them later).
process_strace()
{
strace=$1
# parse in data/system/vendor and parse out /sys/devices/system/...
egrep '\/system\/|\/data\/|\/vendor\/' $strace | egrep -v '\/sys\/devices\/system\/' > bar
fgrep -v '= -1' bar > foo
mv foo bar
# begin_time is seconds since epoch
begin_time=`cat trace.begin`
# replace seconds since epoch with SECONDS SINCE BOOT in the
# strace files
awk -v begin="$begin_time" '{ printf "%f strace ", $1 - begin; $1=""; print $0}' bar > $2
rm bar
}
#
# This function processes the ftrace file, removing the fields that we don't care
# about, breaks up the ftrace file into one file per pid.
# Input : One single fstrace file.
# Output : Multiple fstrace.pid files.
prep_fstrace()
{
# Remove leading junk
fgrep android_fs_data $1 | sed 's/^.* \[.*\] //' | sed s/://g | sed s/,//g > foo
# Sanitize the filenames, removing spaces within the filename etc
sed 's/android_fs_dataread_start/read/' foo > bar1
mv bar1 bar
# First column is timestamp SECONDS SINCE BOOT
awk '{ print $2, "ftrace", $3, $5, $7, $9, $13 }' bar > foo
#awk '{ s ="" ; for (i=2; i <= NF ; i++) s = s $i " "; print s}' bar > foo
rm bar
# Get all the uniq pids
awk '{print $7}' foo | sort | uniq > pidlist
for i in `cat pidlist`
do
awk -v pid=$i '{ if (pid == $7) print $0}' foo > fstrace.$i
done
rm pidlist
rm foo
}
# Merge straces and ftraces.
# The goal here is to catch mmap'ed IO (reads) that won't be in the
# strace file. The algorithm is to look for mmaps in the strace file,
# use the files tha are mmap'ed to search in the ftraces to pick up
# tracepoints from there, and merge those with the straces.
# The output of this function is a set of parsed_input_trace.<pid>
# files, that can then be compiled into .wl files
merge_compile()
{
for stracefile in trace.*
do
if [ $stracefile == trace.begin ] || [ $stracefile == trace.tar ];
then
continue
fi
# Get the pid from the strace filename (pid is the extension)
pid=${stracefile##*.}
process_strace $stracefile foo.$pid
if ! [ -s foo.$pid ]; then
rm foo.$pid
continue
fi
#
# If we have matching strace and ftrace files, then look for mmaps in
# the strace pluck the corresponding entries for the mmap (mmaped IO)
# from the ftrace and merge them into the strace
#
if [ -f fstrace.$pid ]; then
fgrep mmap foo.$pid > bar
if [ -s bar ]; then
# Get all the unique mmap'ed filenames from the strace
awk '{ print $7 }' bar | sed 's/^[^<]*<//g' | sed 's/>,//g' > mapped_files
# Pluck all the lines from the ftrace corresponding to the mmaps
cat /dev/null > footemp
for j in `sort mapped_files | uniq`
do
# Merge the readpage(s) traces from the ftrace into strace
# for this mmaped file.
grep -w $j fstrace.$pid > foobar
if [ $? == 0 ]; then
sort foo.$pid foobar >> footemp
fi
rm foobar
done
rm mapped_files
if [ -s footemp ]; then
mv footemp parsed_input_trace.$pid
else
mv foo.$pid parsed_input_trace.$pid
fi
else
mv foo.$pid parsed_input_trace.$pid
fi
rm bar
else
mv foo.$pid parsed_input_trace.$pid
fi
echo compiling parsed_input_trace.$pid
compile_ioshark parsed_input_trace.$pid $pid.wl
rm parsed_input_trace.$pid
rm -f foo.$pid
done
}
catch_sigint()
{
echo "signal INT received, killing streaming trace capture"
ps_line=`ps -ef | grep trace_pipe | grep adb `
if [ $? == 0 ]; then
echo Killing `echo $ps_line | awk '{s = ""; for (i=8; i <= NF ; i++) s = s $i " "; print s}' `
kill `echo $ps_line | awk '{print $2}' `
fi
ps_line=`ps -ef | grep strace | grep adb `
if [ $? == 0 ]; then
echo Killing `echo $ps_line | awk '{s = ""; for (i=8; i <= NF ; i++) s = s $i " "; print s}' `
kill `echo $ps_line | awk '{print $2}' `
fi
}
enable_tracepoints()
{
adb shell "echo 1 > /sys/kernel/debug/tracing/events/android_fs/android_fs_dataread_start/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/tracing_on"
}
disable_tracepoints()
{
adb shell "echo 0 > /sys/kernel/debug/tracing/events/android_fs/android_fs_dataread_start/enable"
adb shell "echo 0 > /sys/kernel/debug/tracing/tracing_on"
}
kill_traces()
{
ps_line=`ps -ef | grep trace_pipe | grep adb `
if [ $? == 0 ]; then
echo Killing `echo $ps_line | awk '{s = ""; for (i=8; i <= NF ; i++) s = s $i " "; print s}' `
kill `echo $ps_line | awk '{print $2}' `
fi
ps_line=`ps -ef | grep strace | grep adb `
if [ $? == 0 ]; then
echo Killing `echo $ps_line | awk '{s = ""; for (i=8; i <= NF ; i++) s = s $i " "; print s}' `
kill `echo $ps_line | awk '{print $2}' `
fi
}
catch_sigint()
{
echo "signal INT received, killing streaming trace capture"
kill_traces
}
# main() starts here
adb root && adb wait-for-device
enable_tracepoints
trap 'catch_sigint' INT
adb shell 'ps' | grep zygote > zygote_pids
fgrep -v grep zygote_pids > bar
mv bar zygote_pids
pid1=`grep -w zygote zygote_pids | awk '{print $2}' `
pid2=`grep -w zygote64 zygote_pids | awk '{print $2}' `
rm -f zygote_pids
adb shell "date +%s > /data/local/tmp/trace.begin ; strace -p $pid1,$pid2 -o /data/local/tmp/trace -q -qq -f -ff -y -ttt -e trace=mmap2,read,write,pread64,pwrite64,fsync,fdatasync,openat,close,lseek,_llseek" &
adb shell "cat /sys/kernel/debug/tracing/trace_pipe" > fstrace &
echo "^C this when done with the test"
wait
adb shell 'monkey -p com.android.alarmclock -p com.android.chrome -p com.android.calculator -p com.android.calendar -p com.google.android.calendar -p com.google.android.camera -p com.android.contacts -p com.google.android.gm -p com.android.im -p com.android.launcher -p com.google.android.apps.maps -p com.android.mms -p com.google.android.music -p com.android.phone -p com.google.android.youtube -p com.android.email -p com.google.android.voicesearch -c android.intent.category.LAUNCHER --throttle 200 --ignore-security-exceptions --ignore-crashes --ignore-timeouts -v -v -v 25000'
kill_traces
disable_tracepoints
rm -f trace.*
rm -f fstrace.*
rm -f *.wl
rm -f parsed*
# Get the tracefiles from the device
adb shell 'cd /data/local/tmp ; tar cvf trace.tar trace.*'
adb pull /data/local/tmp/trace.tar
tar xf trace.tar
# Pre-process the ftrace file
prep_fstrace fstrace
# Merge the ftrace file(s) with the strace files
merge_compile
# tar up the .wl files just created
tar cf wl.tar ioshark_filenames *.wl
|