1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "atrace"
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <getopt.h>
22 #include <inttypes.h>
23 #include <signal.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include <zlib.h>
32 
33 #include <fstream>
34 #include <memory>
35 
36 #include <binder/IBinder.h>
37 #include <binder/IServiceManager.h>
38 #include <binder/Parcel.h>
39 
40 #include <android/hardware/atrace/1.0/IAtraceDevice.h>
41 #include <android/hidl/manager/1.0/IServiceManager.h>
42 #include <hidl/ServiceManagement.h>
43 
44 #include <pdx/default_transport/service_utility.h>
45 #include <utils/String8.h>
46 #include <utils/Timers.h>
47 #include <utils/Tokenizer.h>
48 #include <utils/Trace.h>
49 #include <android-base/file.h>
50 #include <android-base/macros.h>
51 #include <android-base/properties.h>
52 #include <android-base/stringprintf.h>
53 
54 using namespace android;
55 using pdx::default_transport::ServiceUtility;
56 using hardware::hidl_vec;
57 using hardware::hidl_string;
58 using hardware::Return;
59 using hardware::atrace::V1_0::IAtraceDevice;
60 using hardware::atrace::V1_0::Status;
61 using hardware::atrace::V1_0::toString;
62 
63 using std::string;
64 
65 #define MAX_SYS_FILES 11
66 
67 const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
68 const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
69 
70 const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
71 const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
72 const char* k_coreServiceCategory = "core_services";
73 const char* k_pdxServiceCategory = "pdx";
74 const char* k_coreServicesProp = "ro.atrace.core.services";
75 
76 typedef enum { OPT, REQ } requiredness  ;
77 
78 struct TracingCategory {
79     // The name identifying the category.
80     const char* name;
81 
82     // A longer description of the category.
83     const char* longname;
84 
85     // The userland tracing tags that the category enables.
86     uint64_t tags;
87 
88     // The fname==NULL terminated list of /sys/ files that the category
89     // enables.
90     struct {
91         // Whether the file must be writable in order to enable the tracing
92         // category.
93         requiredness required;
94 
95         // The path to the enable file.
96         const char* path;
97     } sysfiles[MAX_SYS_FILES];
98 };
99 
100 /* Tracing categories */
101 static const TracingCategory k_categories[] = {
102     { "gfx",        "Graphics",                 ATRACE_TAG_GRAPHICS, { } },
103     { "input",      "Input",                    ATRACE_TAG_INPUT, { } },
104     { "view",       "View System",              ATRACE_TAG_VIEW, { } },
105     { "webview",    "WebView",                  ATRACE_TAG_WEBVIEW, { } },
106     { "wm",         "Window Manager",           ATRACE_TAG_WINDOW_MANAGER, { } },
107     { "am",         "Activity Manager",         ATRACE_TAG_ACTIVITY_MANAGER, { } },
108     { "sm",         "Sync Manager",             ATRACE_TAG_SYNC_MANAGER, { } },
109     { "audio",      "Audio",                    ATRACE_TAG_AUDIO, { } },
110     { "video",      "Video",                    ATRACE_TAG_VIDEO, { } },
111     { "camera",     "Camera",                   ATRACE_TAG_CAMERA, { } },
112     { "hal",        "Hardware Modules",         ATRACE_TAG_HAL, { } },
113     { "res",        "Resource Loading",         ATRACE_TAG_RESOURCES, { } },
114     { "dalvik",     "Dalvik VM",                ATRACE_TAG_DALVIK, { } },
115     { "rs",         "RenderScript",             ATRACE_TAG_RS, { } },
116     { "bionic",     "Bionic C Library",         ATRACE_TAG_BIONIC, { } },
117     { "power",      "Power Management",         ATRACE_TAG_POWER, { } },
118     { "pm",         "Package Manager",          ATRACE_TAG_PACKAGE_MANAGER, { } },
119     { "ss",         "System Server",            ATRACE_TAG_SYSTEM_SERVER, { } },
120     { "database",   "Database",                 ATRACE_TAG_DATABASE, { } },
121     { "network",    "Network",                  ATRACE_TAG_NETWORK, { } },
122     { "adb",        "ADB",                      ATRACE_TAG_ADB, { } },
123     { "vibrator",   "Vibrator",                 ATRACE_TAG_VIBRATOR, { } },
124     { "aidl",       "AIDL calls",               ATRACE_TAG_AIDL, { } },
125     { "nnapi",      "NNAPI",                    ATRACE_TAG_NNAPI, { } },
126     { "rro",        "Runtime Resource Overlay", ATRACE_TAG_RRO, { } },
127     { k_coreServiceCategory, "Core services", 0, { } },
128     { k_pdxServiceCategory, "PDX services", 0, { } },
129     { "sched",      "CPU Scheduling",   0, {
130         { REQ,      "events/sched/sched_switch/enable" },
131         { REQ,      "events/sched/sched_wakeup/enable" },
132         { OPT,      "events/sched/sched_waking/enable" },
133         { OPT,      "events/sched/sched_blocked_reason/enable" },
134         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
135         { OPT,      "events/sched/sched_pi_setprio/enable" },
136         { OPT,      "events/sched/sched_process_exit/enable" },
137         { OPT,      "events/cgroup/enable" },
138         { OPT,      "events/oom/oom_score_adj_update/enable" },
139         { OPT,      "events/task/task_rename/enable" },
140         { OPT,      "events/task/task_newtask/enable" },
141     } },
142     { "irq",        "IRQ Events",   0, {
143         { REQ,      "events/irq/enable" },
144         { OPT,      "events/ipi/enable" },
145     } },
146     { "irqoff",     "IRQ-disabled code section tracing", 0, {
147         { REQ,      "events/preemptirq/irq_enable/enable" },
148         { REQ,      "events/preemptirq/irq_disable/enable" },
149     } },
150     { "preemptoff", "Preempt-disabled code section tracing", 0, {
151         { REQ,      "events/preemptirq/preempt_enable/enable" },
152         { REQ,      "events/preemptirq/preempt_disable/enable" },
153     } },
154     { "i2c",        "I2C Events",   0, {
155         { REQ,      "events/i2c/enable" },
156         { REQ,      "events/i2c/i2c_read/enable" },
157         { REQ,      "events/i2c/i2c_write/enable" },
158         { REQ,      "events/i2c/i2c_result/enable" },
159         { REQ,      "events/i2c/i2c_reply/enable" },
160         { OPT,      "events/i2c/smbus_read/enable" },
161         { OPT,      "events/i2c/smbus_write/enable" },
162         { OPT,      "events/i2c/smbus_result/enable" },
163         { OPT,      "events/i2c/smbus_reply/enable" },
164     } },
165     { "freq",       "CPU Frequency",    0, {
166         { REQ,      "events/power/cpu_frequency/enable" },
167         { OPT,      "events/power/clock_set_rate/enable" },
168         { OPT,      "events/power/clock_disable/enable" },
169         { OPT,      "events/power/clock_enable/enable" },
170         { OPT,      "events/clk/clk_set_rate/enable" },
171         { OPT,      "events/clk/clk_disable/enable" },
172         { OPT,      "events/clk/clk_enable/enable" },
173         { OPT,      "events/power/cpu_frequency_limits/enable" },
174         { OPT,      "events/power/suspend_resume/enable" },
175         { OPT,      "events/cpuhp/cpuhp_enter/enable" },
176         { OPT,      "events/cpuhp/cpuhp_exit/enable" },
177     } },
178     { "membus",     "Memory Bus Utilization", 0, {
179         { REQ,      "events/memory_bus/enable" },
180     } },
181     { "idle",       "CPU Idle",         0, {
182         { REQ,      "events/power/cpu_idle/enable" },
183     } },
184     { "disk",       "Disk I/O",         0, {
185         { OPT,      "events/f2fs/f2fs_sync_file_enter/enable" },
186         { OPT,      "events/f2fs/f2fs_sync_file_exit/enable" },
187         { OPT,      "events/f2fs/f2fs_write_begin/enable" },
188         { OPT,      "events/f2fs/f2fs_write_end/enable" },
189         { OPT,      "events/ext4/ext4_da_write_begin/enable" },
190         { OPT,      "events/ext4/ext4_da_write_end/enable" },
191         { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
192         { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
193         { REQ,      "events/block/block_rq_issue/enable" },
194         { REQ,      "events/block/block_rq_complete/enable" },
195     } },
196     { "mmc",        "eMMC commands",    0, {
197         { REQ,      "events/mmc/enable" },
198     } },
199     { "load",       "CPU Load",         0, {
200         { REQ,      "events/cpufreq_interactive/enable" },
201     } },
202     { "sync",       "Synchronization",  0, {
203         // linux kernel < 4.9
204         { OPT,      "events/sync/enable" },
205         // linux kernel == 4.9.x
206         { OPT,      "events/fence/enable" },
207         // linux kernel > 4.9
208         { OPT,      "events/dma_fence/enable" },
209     } },
210     { "workq",      "Kernel Workqueues", 0, {
211         { REQ,      "events/workqueue/enable" },
212     } },
213     { "memreclaim", "Kernel Memory Reclaim", 0, {
214         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
215         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
216         { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
217         { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
218         { OPT,      "events/lowmemorykiller/enable" },
219     } },
220     { "regulators",  "Voltage and Current Regulators", 0, {
221         { REQ,      "events/regulator/enable" },
222     } },
223     { "binder_driver", "Binder Kernel driver", 0, {
224         { REQ,      "events/binder/binder_transaction/enable" },
225         { REQ,      "events/binder/binder_transaction_received/enable" },
226         { REQ,      "events/binder/binder_transaction_alloc_buf/enable" },
227         { OPT,      "events/binder/binder_set_priority/enable" },
228     } },
229     { "binder_lock", "Binder global lock trace", 0, {
230         { OPT,      "events/binder/binder_lock/enable" },
231         { OPT,      "events/binder/binder_locked/enable" },
232         { OPT,      "events/binder/binder_unlock/enable" },
233     } },
234     { "pagecache",  "Page cache", 0, {
235         { REQ,      "events/filemap/enable" },
236     } },
237     { "memory",  "Memory", 0, {
238         { OPT,      "events/mm_event/mm_event_record/enable" },
239         { OPT,      "events/kmem/rss_stat/enable" },
240         { OPT,      "events/kmem/ion_heap_grow/enable" },
241         { OPT,      "events/kmem/ion_heap_shrink/enable" },
242         { OPT,      "events/ion/ion_stat/enable" },
243     } },
244     { "thermal",  "Thermal event", 0, {
245         { REQ,      "events/thermal/thermal_temperature/enable" },
246         { OPT,      "events/thermal/cdev_update/enable" },
247     } },
248 };
249 
250 struct TracingVendorCategory {
251     // The name identifying the category.
252     std::string name;
253 
254     // A longer description of the category.
255     std::string description;
256 
257     // If the category is enabled through command.
258     bool enabled;
259 
TracingVendorCategoryTracingVendorCategory260     TracingVendorCategory(string &&name, string &&description, bool enabled)
261             : name(std::move(name))
262             , description(std::move(description))
263             , enabled(enabled)
264     {}
265 };
266 
267 /* Command line options */
268 static int g_traceDurationSeconds = 5;
269 static bool g_traceOverwrite = false;
270 static int g_traceBufferSizeKB = 2048;
271 static bool g_compress = false;
272 static bool g_nohup = false;
273 static int g_initialSleepSecs = 0;
274 static const char* g_categoriesFile = nullptr;
275 static const char* g_kernelTraceFuncs = nullptr;
276 static const char* g_debugAppCmdLine = "";
277 static const char* g_outputFile = nullptr;
278 
279 /* Global state */
280 static bool g_tracePdx = false;
281 static bool g_traceAborted = false;
282 static bool g_categoryEnables[arraysize(k_categories)] = {};
283 static std::string g_traceFolder;
284 static sp<IAtraceDevice> g_atraceHal;
285 static std::vector<TracingVendorCategory> g_vendorCategories;
286 
287 /* Sys file paths */
288 static const char* k_traceClockPath =
289     "trace_clock";
290 
291 static const char* k_traceBufferSizePath =
292     "buffer_size_kb";
293 
294 #if 0
295 // TODO: Re-enable after stabilization
296 static const char* k_traceCmdlineSizePath =
297     "saved_cmdlines_size";
298 #endif
299 
300 static const char* k_tracingOverwriteEnablePath =
301     "options/overwrite";
302 
303 static const char* k_currentTracerPath =
304     "current_tracer";
305 
306 static const char* k_printTgidPath =
307     "options/print-tgid";
308 
309 static const char* k_recordTgidPath =
310     "options/record-tgid";
311 
312 static const char* k_funcgraphAbsTimePath =
313     "options/funcgraph-abstime";
314 
315 static const char* k_funcgraphCpuPath =
316     "options/funcgraph-cpu";
317 
318 static const char* k_funcgraphProcPath =
319     "options/funcgraph-proc";
320 
321 static const char* k_funcgraphFlatPath =
322     "options/funcgraph-flat";
323 
324 static const char* k_ftraceFilterPath =
325     "set_ftrace_filter";
326 
327 static const char* k_tracingOnPath =
328     "tracing_on";
329 
330 static const char* k_tracePath =
331     "trace";
332 
333 static const char* k_traceStreamPath =
334     "trace_pipe";
335 
336 static const char* k_traceMarkerPath =
337     "trace_marker";
338 
339 // Check whether a file exists.
fileExists(const char * filename)340 static bool fileExists(const char* filename) {
341     return access((g_traceFolder + filename).c_str(), F_OK) != -1;
342 }
343 
344 // Check whether a file is writable.
fileIsWritable(const char * filename)345 static bool fileIsWritable(const char* filename) {
346     return access((g_traceFolder + filename).c_str(), W_OK) != -1;
347 }
348 
349 // Truncate a file.
truncateFile(const char * path)350 static bool truncateFile(const char* path)
351 {
352     // This uses creat rather than truncate because some of the debug kernel
353     // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
354     // calls to truncate, but they are cleared by calls to creat.
355     int traceFD = creat((g_traceFolder + path).c_str(), 0);
356     if (traceFD == -1) {
357         fprintf(stderr, "error truncating %s: %s (%d)\n", (g_traceFolder + path).c_str(),
358             strerror(errno), errno);
359         return false;
360     }
361 
362     close(traceFD);
363 
364     return true;
365 }
366 
_writeStr(const char * filename,const char * str,int flags)367 static bool _writeStr(const char* filename, const char* str, int flags)
368 {
369     std::string fullFilename = g_traceFolder + filename;
370     int fd = open(fullFilename.c_str(), flags);
371     if (fd == -1) {
372         fprintf(stderr, "error opening %s: %s (%d)\n", fullFilename.c_str(),
373                 strerror(errno), errno);
374         return false;
375     }
376 
377     bool ok = true;
378     ssize_t len = strlen(str);
379     if (write(fd, str, len) != len) {
380         fprintf(stderr, "error writing to %s: %s (%d)\n", fullFilename.c_str(),
381                 strerror(errno), errno);
382         ok = false;
383     }
384 
385     close(fd);
386 
387     return ok;
388 }
389 
390 // Write a string to a file, returning true if the write was successful.
writeStr(const char * filename,const char * str)391 static bool writeStr(const char* filename, const char* str)
392 {
393     return _writeStr(filename, str, O_WRONLY);
394 }
395 
396 // Append a string to a file, returning true if the write was successful.
appendStr(const char * filename,const char * str)397 static bool appendStr(const char* filename, const char* str)
398 {
399     return _writeStr(filename, str, O_APPEND|O_WRONLY);
400 }
401 
writeClockSyncMarker()402 static void writeClockSyncMarker()
403 {
404   char buffer[128];
405   int len = 0;
406   int fd = open((g_traceFolder + k_traceMarkerPath).c_str(), O_WRONLY);
407   if (fd == -1) {
408       fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
409               strerror(errno), errno);
410       return;
411   }
412   float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
413 
414   len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
415   if (write(fd, buffer, len) != len) {
416       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
417   }
418 
419   int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
420   len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
421   if (write(fd, buffer, len) != len) {
422       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
423   }
424 
425   close(fd);
426 }
427 
428 // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
429 // file.
setKernelOptionEnable(const char * filename,bool enable)430 static bool setKernelOptionEnable(const char* filename, bool enable)
431 {
432     return writeStr(filename, enable ? "1" : "0");
433 }
434 
435 // Check whether the category is supported on the device with the current
436 // rootness.  A category is supported only if all its required /sys/ files are
437 // writable and if enabling the category will enable one or more tracing tags
438 // or /sys/ files.
isCategorySupported(const TracingCategory & category)439 static bool isCategorySupported(const TracingCategory& category)
440 {
441     if (strcmp(category.name, k_coreServiceCategory) == 0) {
442         return !android::base::GetProperty(k_coreServicesProp, "").empty();
443     }
444 
445     if (strcmp(category.name, k_pdxServiceCategory) == 0) {
446         return true;
447     }
448 
449     bool ok = category.tags != 0;
450     for (int i = 0; i < MAX_SYS_FILES; i++) {
451         const char* path = category.sysfiles[i].path;
452         bool req = category.sysfiles[i].required == REQ;
453         if (path != nullptr) {
454             if (fileIsWritable(path)) {
455                 ok = true;
456             } else if (req) {
457                 return false;
458             }
459         }
460     }
461     return ok;
462 }
463 
464 // Check whether the category would be supported on the device if the user
465 // were root.  This function assumes that root is able to write to any file
466 // that exists.  It performs the same logic as isCategorySupported, but it
467 // uses file existence rather than writability in the /sys/ file checks.
isCategorySupportedForRoot(const TracingCategory & category)468 static bool isCategorySupportedForRoot(const TracingCategory& category)
469 {
470     bool ok = category.tags != 0;
471     for (int i = 0; i < MAX_SYS_FILES; i++) {
472         const char* path = category.sysfiles[i].path;
473         bool req = category.sysfiles[i].required == REQ;
474         if (path != nullptr) {
475             if (req) {
476                 if (!fileExists(path)) {
477                     return false;
478                 } else {
479                     ok = true;
480                 }
481             } else {
482                 ok |= fileExists(path);
483             }
484         }
485     }
486     return ok;
487 }
488 
489 // Enable or disable overwriting of the kernel trace buffers.  Disabling this
490 // will cause tracing to stop once the trace buffers have filled up.
setTraceOverwriteEnable(bool enable)491 static bool setTraceOverwriteEnable(bool enable)
492 {
493     return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
494 }
495 
496 // Set the user initiated trace property
setUserInitiatedTraceProperty(bool enable)497 static bool setUserInitiatedTraceProperty(bool enable)
498 {
499     if (!android::base::SetProperty(k_userInitiatedTraceProperty, enable ? "1" : "")) {
500         fprintf(stderr, "error setting user initiated strace system property\n");
501         return false;
502     }
503     return true;
504 }
505 
506 // Enable or disable kernel tracing.
setTracingEnabled(bool enable)507 static bool setTracingEnabled(bool enable)
508 {
509     return setKernelOptionEnable(k_tracingOnPath, enable);
510 }
511 
512 // Clear the contents of the kernel trace.
clearTrace()513 static bool clearTrace()
514 {
515     return truncateFile(k_tracePath);
516 }
517 
518 // Set the size of the kernel's trace buffer in kilobytes.
setTraceBufferSizeKB(int size)519 static bool setTraceBufferSizeKB(int size)
520 {
521     char str[32] = "1";
522     if (size < 1) {
523         size = 1;
524     }
525     snprintf(str, 32, "%d", size);
526     return writeStr(k_traceBufferSizePath, str);
527 }
528 
529 #if 0
530 // TODO: Re-enable after stabilization
531 // Set the default size of cmdline hashtable
532 static bool setCmdlineSize()
533 {
534     if (fileExists(k_traceCmdlineSizePath)) {
535         return writeStr(k_traceCmdlineSizePath, "8192");
536     }
537     return true;
538 }
539 #endif
540 
541 // Set the clock to the best available option while tracing. Use 'boot' if it's
542 // available; otherwise, use 'mono'. If neither are available use 'global'.
543 // Any write to the trace_clock sysfs file will reset the buffer, so only
544 // update it if the requested value is not the current value.
setClock()545 static bool setClock()
546 {
547     std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
548     std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
549         std::istreambuf_iterator<char>());
550 
551     std::string newClock;
552     if (clockStr.find("boot") != std::string::npos) {
553         newClock = "boot";
554     } else if (clockStr.find("mono") != std::string::npos) {
555         newClock = "mono";
556     } else {
557         newClock = "global";
558     }
559 
560     size_t begin = clockStr.find('[') + 1;
561     size_t end = clockStr.find(']');
562     if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
563         return true;
564     }
565     return writeStr(k_traceClockPath, newClock.c_str());
566 }
567 
setPrintTgidEnableIfPresent(bool enable)568 static bool setPrintTgidEnableIfPresent(bool enable)
569 {
570     // Pre-4.13 this was options/print-tgid as an android-specific option.
571     // In 4.13+ this is an upstream option called options/record-tgid
572     // Both options produce the same ftrace format change
573     if (fileExists(k_printTgidPath)) {
574         return setKernelOptionEnable(k_printTgidPath, enable);
575     }
576     if (fileExists(k_recordTgidPath)) {
577         return setKernelOptionEnable(k_recordTgidPath, enable);
578     }
579     return true;
580 }
581 
582 // Set the trace tags that userland tracing uses, and poke the running
583 // processes to pick up the new value.
setTagsProperty(uint64_t tags)584 static bool setTagsProperty(uint64_t tags)
585 {
586     std::string value = android::base::StringPrintf("%#" PRIx64, tags);
587     if (!android::base::SetProperty(k_traceTagsProperty, value)) {
588         fprintf(stderr, "error setting trace tags system property\n");
589         return false;
590     }
591     return true;
592 }
593 
clearAppProperties()594 static void clearAppProperties()
595 {
596     if (!android::base::SetProperty(k_traceAppsNumberProperty, "")) {
597         fprintf(stderr, "failed to clear system property: %s",
598               k_traceAppsNumberProperty);
599     }
600 }
601 
602 // Set the system property that indicates which apps should perform
603 // application-level tracing.
setAppCmdlineProperty(char * cmdline)604 static bool setAppCmdlineProperty(char* cmdline)
605 {
606     int i = 0;
607     char* start = cmdline;
608     while (start != nullptr) {
609         char* end = strchr(start, ',');
610         if (end != nullptr) {
611             *end = '\0';
612             end++;
613         }
614         std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
615         if (!android::base::SetProperty(key, start)) {
616             fprintf(stderr, "error setting trace app %d property to %s\n", i, key.c_str());
617             clearAppProperties();
618             return false;
619         }
620         start = end;
621         i++;
622     }
623 
624     std::string value = android::base::StringPrintf("%d", i);
625     if (!android::base::SetProperty(k_traceAppsNumberProperty, value)) {
626         fprintf(stderr, "error setting trace app number property to %s\n", value.c_str());
627         clearAppProperties();
628         return false;
629     }
630     return true;
631 }
632 
633 // Disable all /sys/ enable files.
disableKernelTraceEvents()634 static bool disableKernelTraceEvents() {
635     bool ok = true;
636     for (size_t i = 0; i < arraysize(k_categories); i++) {
637         const TracingCategory &c = k_categories[i];
638         for (int j = 0; j < MAX_SYS_FILES; j++) {
639             const char* path = c.sysfiles[j].path;
640             if (path != nullptr && fileIsWritable(path)) {
641                 ok &= setKernelOptionEnable(path, false);
642             }
643         }
644     }
645     return ok;
646 }
647 
648 // Verify that the comma separated list of functions are being traced by the
649 // kernel.
verifyKernelTraceFuncs(const char * funcs)650 static bool verifyKernelTraceFuncs(const char* funcs)
651 {
652     std::string buf;
653     if (!android::base::ReadFileToString(g_traceFolder + k_ftraceFilterPath, &buf)) {
654          fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
655             strerror(errno), errno);
656          return false;
657     }
658 
659     String8 funcList = String8::format("\n%s",buf.c_str());
660 
661     // Make sure that every function listed in funcs is in the list we just
662     // read from the kernel, except for wildcard inputs.
663     bool ok = true;
664     char* myFuncs = strdup(funcs);
665     char* func = strtok(myFuncs, ",");
666     while (func) {
667         if (!strchr(func, '*')) {
668             String8 fancyFunc = String8::format("\n%s\n", func);
669             bool found = funcList.find(fancyFunc.string(), 0) >= 0;
670             if (!found || func[0] == '\0') {
671                 fprintf(stderr, "error: \"%s\" is not a valid kernel function "
672                         "to trace.\n", func);
673                 ok = false;
674             }
675         }
676         func = strtok(nullptr, ",");
677     }
678     free(myFuncs);
679     return ok;
680 }
681 
682 // Set the comma separated list of functions that the kernel is to trace.
setKernelTraceFuncs(const char * funcs)683 static bool setKernelTraceFuncs(const char* funcs)
684 {
685     bool ok = true;
686 
687     if (funcs == nullptr || funcs[0] == '\0') {
688         // Disable kernel function tracing.
689         if (fileIsWritable(k_currentTracerPath)) {
690             ok &= writeStr(k_currentTracerPath, "nop");
691         }
692         if (fileIsWritable(k_ftraceFilterPath)) {
693             ok &= truncateFile(k_ftraceFilterPath);
694         }
695     } else {
696         // Enable kernel function tracing.
697         ok &= writeStr(k_currentTracerPath, "function_graph");
698         ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
699         ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
700         ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
701         ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
702 
703         // Set the requested filter functions.
704         ok &= truncateFile(k_ftraceFilterPath);
705         char* myFuncs = strdup(funcs);
706         char* func = strtok(myFuncs, ",");
707         while (func) {
708             ok &= appendStr(k_ftraceFilterPath, func);
709             func = strtok(nullptr, ",");
710         }
711         free(myFuncs);
712 
713         // Verify that the set functions are being traced.
714         if (ok) {
715             ok &= verifyKernelTraceFuncs(funcs);
716         }
717     }
718 
719     return ok;
720 }
721 
setCategoryEnable(const char * name)722 static bool setCategoryEnable(const char* name)
723 {
724     bool vendor_found = false;
725     for (auto &c : g_vendorCategories) {
726         if (strcmp(name, c.name.c_str()) == 0) {
727             c.enabled = true;
728             vendor_found = true;
729         }
730     }
731     for (size_t i = 0; i < arraysize(k_categories); i++) {
732         const TracingCategory& c = k_categories[i];
733         if (strcmp(name, c.name) == 0) {
734             if (isCategorySupported(c)) {
735                 g_categoryEnables[i] = true;
736                 return true;
737             } else {
738                 if (isCategorySupportedForRoot(c)) {
739                     fprintf(stderr, "error: category \"%s\" requires root "
740                             "privileges.\n", name);
741                 } else {
742                     fprintf(stderr, "error: category \"%s\" is not supported "
743                             "on this device.\n", name);
744                 }
745                 return false;
746             }
747         }
748     }
749     if (vendor_found) {
750         return true;
751     }
752     fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
753     return false;
754 }
755 
setCategoriesEnableFromFile(const char * categories_file)756 static bool setCategoriesEnableFromFile(const char* categories_file)
757 {
758     if (!categories_file) {
759         return true;
760     }
761     Tokenizer* tokenizer = nullptr;
762     if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
763         return false;
764     }
765     bool ok = true;
766     while (!tokenizer->isEol()) {
767         String8 token = tokenizer->nextToken(" ");
768         if (token.isEmpty()) {
769             tokenizer->skipDelimiters(" ");
770             continue;
771         }
772         ok &= setCategoryEnable(token.string());
773     }
774     delete tokenizer;
775     return ok;
776 }
777 
setUpUserspaceTracing()778 static bool setUpUserspaceTracing()
779 {
780     bool ok = true;
781 
782     // Set up the tags property.
783     uint64_t tags = 0;
784     for (size_t i = 0; i < arraysize(k_categories); i++) {
785         if (g_categoryEnables[i]) {
786             const TracingCategory &c = k_categories[i];
787             tags |= c.tags;
788         }
789     }
790 
791     bool coreServicesTagEnabled = false;
792     for (size_t i = 0; i < arraysize(k_categories); i++) {
793         if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
794             coreServicesTagEnabled = g_categoryEnables[i];
795         }
796 
797         // Set whether to poke PDX services in this session.
798         if (strcmp(k_categories[i].name, k_pdxServiceCategory) == 0) {
799             g_tracePdx = g_categoryEnables[i];
800         }
801     }
802 
803     std::string packageList(g_debugAppCmdLine);
804     if (coreServicesTagEnabled) {
805         if (!packageList.empty()) {
806             packageList += ",";
807         }
808         packageList += android::base::GetProperty(k_coreServicesProp, "");
809     }
810     ok &= setAppCmdlineProperty(&packageList[0]);
811     ok &= setTagsProperty(tags);
812     if (g_tracePdx) {
813         ok &= ServiceUtility::PokeServices();
814     }
815 
816     return ok;
817 }
818 
cleanUpUserspaceTracing()819 static void cleanUpUserspaceTracing()
820 {
821     setTagsProperty(0);
822     clearAppProperties();
823 
824     if (g_tracePdx) {
825         ServiceUtility::PokeServices();
826     }
827 }
828 
829 
830 // Set all the kernel tracing settings to the desired state for this trace
831 // capture.
setUpKernelTracing()832 static bool setUpKernelTracing()
833 {
834     bool ok = true;
835 
836     ok &= setUserInitiatedTraceProperty(true);
837 
838     // Set up the tracing options.
839     ok &= setCategoriesEnableFromFile(g_categoriesFile);
840     ok &= setTraceOverwriteEnable(g_traceOverwrite);
841     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
842     // TODO: Re-enable after stabilization
843     //ok &= setCmdlineSize();
844     ok &= setClock();
845     ok &= setPrintTgidEnableIfPresent(true);
846     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
847 
848     // Disable all the sysfs enables.  This is done as a separate loop from
849     // the enables to allow the same enable to exist in multiple categories.
850     ok &= disableKernelTraceEvents();
851 
852     // Enable all the sysfs enables that are in an enabled category.
853     for (size_t i = 0; i < arraysize(k_categories); i++) {
854         if (g_categoryEnables[i]) {
855             const TracingCategory &c = k_categories[i];
856             for (int j = 0; j < MAX_SYS_FILES; j++) {
857                 const char* path = c.sysfiles[j].path;
858                 bool required = c.sysfiles[j].required == REQ;
859                 if (path != nullptr) {
860                     if (fileIsWritable(path)) {
861                         ok &= setKernelOptionEnable(path, true);
862                     } else if (required) {
863                         fprintf(stderr, "error writing file %s\n", path);
864                         ok = false;
865                     }
866                 }
867             }
868         }
869     }
870 
871     return ok;
872 }
873 
874 // Reset all the kernel tracing settings to their default state.
cleanUpKernelTracing()875 static void cleanUpKernelTracing()
876 {
877     // Disable all tracing that we're able to.
878     disableKernelTraceEvents();
879 
880     // Set the options back to their defaults.
881     setTraceOverwriteEnable(true);
882     setTraceBufferSizeKB(1);
883     setPrintTgidEnableIfPresent(false);
884     setKernelTraceFuncs(nullptr);
885     setUserInitiatedTraceProperty(false);
886 }
887 
888 // Enable tracing in the kernel.
startTrace()889 static bool startTrace()
890 {
891     return setTracingEnabled(true);
892 }
893 
894 // Disable tracing in the kernel.
stopTrace()895 static void stopTrace()
896 {
897     setTracingEnabled(false);
898 }
899 
900 // Read data from the tracing pipe and forward to stdout
streamTrace()901 static void streamTrace()
902 {
903     char trace_data[4096];
904     int traceFD = open((g_traceFolder + k_traceStreamPath).c_str(), O_RDWR);
905     if (traceFD == -1) {
906         fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
907                 strerror(errno), errno);
908         return;
909     }
910     while (!g_traceAborted) {
911         ssize_t bytes_read = read(traceFD, trace_data, 4096);
912         if (bytes_read > 0) {
913             write(STDOUT_FILENO, trace_data, bytes_read);
914             fflush(stdout);
915         } else {
916             if (!g_traceAborted) {
917                 fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
918                         bytes_read, errno, strerror(errno));
919             }
920             break;
921         }
922     }
923 }
924 
925 // Read the current kernel trace and write it to stdout.
dumpTrace(int outFd)926 static void dumpTrace(int outFd)
927 {
928     ALOGI("Dumping trace");
929     int traceFD = open((g_traceFolder + k_tracePath).c_str(), O_RDWR);
930     if (traceFD == -1) {
931         fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
932                 strerror(errno), errno);
933         return;
934     }
935 
936     if (g_compress) {
937         z_stream zs;
938         memset(&zs, 0, sizeof(zs));
939 
940         int result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
941         if (result != Z_OK) {
942             fprintf(stderr, "error initializing zlib: %d\n", result);
943             close(traceFD);
944             return;
945         }
946 
947         constexpr size_t bufSize = 64*1024;
948         std::unique_ptr<uint8_t> in(new uint8_t[bufSize]);
949         std::unique_ptr<uint8_t> out(new uint8_t[bufSize]);
950         if (!in || !out) {
951             fprintf(stderr, "couldn't allocate buffers\n");
952             close(traceFD);
953             return;
954         }
955 
956         int flush = Z_NO_FLUSH;
957 
958         zs.next_out = reinterpret_cast<Bytef*>(out.get());
959         zs.avail_out = bufSize;
960 
961         do {
962 
963             if (zs.avail_in == 0) {
964                 // More input is needed.
965                 result = read(traceFD, in.get(), bufSize);
966                 if (result < 0) {
967                     fprintf(stderr, "error reading trace: %s (%d)\n",
968                             strerror(errno), errno);
969                     result = Z_STREAM_END;
970                     break;
971                 } else if (result == 0) {
972                     flush = Z_FINISH;
973                 } else {
974                     zs.next_in = reinterpret_cast<Bytef*>(in.get());
975                     zs.avail_in = result;
976                 }
977             }
978 
979             if (zs.avail_out == 0) {
980                 // Need to write the output.
981                 result = write(outFd, out.get(), bufSize);
982                 if ((size_t)result < bufSize) {
983                     fprintf(stderr, "error writing deflated trace: %s (%d)\n",
984                             strerror(errno), errno);
985                     result = Z_STREAM_END; // skip deflate error message
986                     zs.avail_out = bufSize; // skip the final write
987                     break;
988                 }
989                 zs.next_out = reinterpret_cast<Bytef*>(out.get());
990                 zs.avail_out = bufSize;
991             }
992 
993         } while ((result = deflate(&zs, flush)) == Z_OK);
994 
995         if (result != Z_STREAM_END) {
996             fprintf(stderr, "error deflating trace: %s\n", zs.msg);
997         }
998 
999         if (zs.avail_out < bufSize) {
1000             size_t bytes = bufSize - zs.avail_out;
1001             result = write(outFd, out.get(), bytes);
1002             if ((size_t)result < bytes) {
1003                 fprintf(stderr, "error writing deflated trace: %s (%d)\n",
1004                         strerror(errno), errno);
1005             }
1006         }
1007 
1008         result = deflateEnd(&zs);
1009         if (result != Z_OK) {
1010             fprintf(stderr, "error cleaning up zlib: %d\n", result);
1011         }
1012     } else {
1013         char buf[4096];
1014         ssize_t rc;
1015         while ((rc = TEMP_FAILURE_RETRY(read(traceFD, buf, sizeof(buf)))) > 0) {
1016             if (!android::base::WriteFully(outFd, buf, rc)) {
1017                 fprintf(stderr, "error writing trace: %s\n", strerror(errno));
1018                 break;
1019             }
1020         }
1021         if (rc == -1) {
1022             fprintf(stderr, "error dumping trace: %s\n", strerror(errno));
1023         }
1024     }
1025 
1026     close(traceFD);
1027 }
1028 
handleSignal(int)1029 static void handleSignal(int /*signo*/)
1030 {
1031     if (!g_nohup) {
1032         g_traceAborted = true;
1033     }
1034 }
1035 
registerSigHandler()1036 static void registerSigHandler()
1037 {
1038     struct sigaction sa;
1039     sigemptyset(&sa.sa_mask);
1040     sa.sa_flags = 0;
1041     sa.sa_handler = handleSignal;
1042     sigaction(SIGHUP, &sa, nullptr);
1043     sigaction(SIGINT, &sa, nullptr);
1044     sigaction(SIGQUIT, &sa, nullptr);
1045     sigaction(SIGTERM, &sa, nullptr);
1046 }
1047 
listSupportedCategories()1048 static void listSupportedCategories()
1049 {
1050     for (size_t i = 0; i < arraysize(k_categories); i++) {
1051         const TracingCategory& c = k_categories[i];
1052         if (isCategorySupported(c)) {
1053             printf("  %10s - %s\n", c.name, c.longname);
1054         }
1055     }
1056     for (const auto &c : g_vendorCategories) {
1057         printf("  %10s - %s (HAL)\n", c.name.c_str(), c.description.c_str());
1058     }
1059 }
1060 
1061 // Print the command usage help to stderr.
showHelp(const char * cmd)1062 static void showHelp(const char *cmd)
1063 {
1064     fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
1065     fprintf(stderr, "options include:\n"
1066                     "  -a appname      enable app-level tracing for a comma "
1067                         "separated list of cmdlines; * is a wildcard matching any process\n"
1068                     "  -b N            use a trace buffer size of N KB\n"
1069                     "  -c              trace into a circular buffer\n"
1070                     "  -f filename     use the categories written in a file as space-separated\n"
1071                     "                    values in a line\n"
1072                     "  -k fname,...    trace the listed kernel functions\n"
1073                     "  -n              ignore signals\n"
1074                     "  -s N            sleep for N seconds before tracing [default 0]\n"
1075                     "  -t N            trace for N seconds [default 5]\n"
1076                     "  -z              compress the trace dump\n"
1077                     "  --async_start   start circular trace and return immediately\n"
1078                     "  --async_dump    dump the current contents of circular trace buffer\n"
1079                     "  --async_stop    stop tracing and dump the current contents of circular\n"
1080                     "                    trace buffer\n"
1081                     "  --stream        stream trace to stdout as it enters the trace buffer\n"
1082                     "                    Note: this can take significant CPU time, and is best\n"
1083                     "                    used for measuring things that are not affected by\n"
1084                     "                    CPU performance, like pagecache usage.\n"
1085                     "  --list_categories\n"
1086                     "                  list the available tracing categories\n"
1087                     " -o filename      write the trace to the specified file instead\n"
1088                     "                    of stdout.\n"
1089             );
1090 }
1091 
findTraceFiles()1092 bool findTraceFiles()
1093 {
1094     static const std::string debugfs_path = "/sys/kernel/debug/tracing/";
1095     static const std::string tracefs_path = "/sys/kernel/tracing/";
1096     static const std::string trace_file = "trace_marker";
1097 
1098     bool tracefs = access((tracefs_path + trace_file).c_str(), F_OK) != -1;
1099     bool debugfs = access((debugfs_path + trace_file).c_str(), F_OK) != -1;
1100 
1101     if (!tracefs && !debugfs) {
1102         fprintf(stderr, "Error: Did not find trace folder\n");
1103         return false;
1104     }
1105 
1106     if (tracefs) {
1107         g_traceFolder = tracefs_path;
1108     } else {
1109         g_traceFolder = debugfs_path;
1110     }
1111 
1112     return true;
1113 }
1114 
initVendorCategories()1115 void initVendorCategories()
1116 {
1117     g_atraceHal = IAtraceDevice::getService();
1118 
1119     if (g_atraceHal == nullptr) {
1120         // No atrace HAL
1121         return;
1122     }
1123 
1124     Return<void> ret = g_atraceHal->listCategories(
1125         [](const auto& list) {
1126             g_vendorCategories.reserve(list.size());
1127             for (const auto& category : list) {
1128                 g_vendorCategories.emplace_back(category.name, category.description, false);
1129             }
1130         });
1131     if (!ret.isOk()) {
1132         fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
1133     }
1134 }
1135 
setUpVendorTracing()1136 static bool setUpVendorTracing()
1137 {
1138     if (g_atraceHal == nullptr) {
1139         // No atrace HAL
1140         return true;
1141     }
1142 
1143     std::vector<hidl_string> categories;
1144     for (const auto &c : g_vendorCategories) {
1145         if (c.enabled) {
1146             categories.emplace_back(c.name);
1147         }
1148     }
1149 
1150     if (!categories.size()) {
1151         return true;
1152     }
1153 
1154     auto ret = g_atraceHal->enableCategories(categories);
1155     if (!ret.isOk()) {
1156         fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
1157         return false;
1158     } else if (ret != Status::SUCCESS) {
1159         fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
1160         return false;
1161     }
1162     return true;
1163 }
1164 
cleanUpVendorTracing()1165 static bool cleanUpVendorTracing()
1166 {
1167     if (g_atraceHal == nullptr) {
1168         // No atrace HAL
1169         return true;
1170     }
1171 
1172     if (!g_vendorCategories.size()) {
1173         // No vendor categories
1174         return true;
1175     }
1176 
1177     auto ret = g_atraceHal->disableAllCategories();
1178     if (!ret.isOk()) {
1179         fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
1180         return false;
1181     } else if (ret != Status::SUCCESS) {
1182         fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
1183         return false;
1184     }
1185     return true;
1186 }
1187 
main(int argc,char ** argv)1188 int main(int argc, char **argv)
1189 {
1190     bool async = false;
1191     bool traceStart = true;
1192     bool traceStop = true;
1193     bool traceDump = true;
1194     bool traceStream = false;
1195     bool onlyUserspace = false;
1196 
1197     if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
1198         showHelp(argv[0]);
1199         exit(0);
1200     }
1201 
1202     if (!findTraceFiles()) {
1203         fprintf(stderr, "No trace folder found\n");
1204         exit(-1);
1205     }
1206 
1207     initVendorCategories();
1208 
1209     for (;;) {
1210         int ret;
1211         int option_index = 0;
1212         static struct option long_options[] = {
1213             {"async_start",       no_argument, nullptr,  0 },
1214             {"async_stop",        no_argument, nullptr,  0 },
1215             {"async_dump",        no_argument, nullptr,  0 },
1216             {"only_userspace",    no_argument, nullptr,  0 },
1217             {"list_categories",   no_argument, nullptr,  0 },
1218             {"stream",            no_argument, nullptr,  0 },
1219             {nullptr,                       0, nullptr,  0 }
1220         };
1221 
1222         ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
1223                           long_options, &option_index);
1224 
1225         if (ret < 0) {
1226             for (int i = optind; i < argc; i++) {
1227                 if (!setCategoryEnable(argv[i])) {
1228                     fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
1229                     exit(1);
1230                 }
1231             }
1232             break;
1233         }
1234 
1235         switch(ret) {
1236             case 'a':
1237                 g_debugAppCmdLine = optarg;
1238             break;
1239 
1240             case 'b':
1241                 g_traceBufferSizeKB = atoi(optarg);
1242             break;
1243 
1244             case 'c':
1245                 g_traceOverwrite = true;
1246             break;
1247 
1248             case 'f':
1249                 g_categoriesFile = optarg;
1250             break;
1251 
1252             case 'k':
1253                 g_kernelTraceFuncs = optarg;
1254             break;
1255 
1256             case 'n':
1257                 g_nohup = true;
1258             break;
1259 
1260             case 's':
1261                 g_initialSleepSecs = atoi(optarg);
1262             break;
1263 
1264             case 't':
1265                 g_traceDurationSeconds = atoi(optarg);
1266             break;
1267 
1268             case 'z':
1269                 g_compress = true;
1270             break;
1271 
1272             case 'o':
1273                 g_outputFile = optarg;
1274             break;
1275 
1276             case 0:
1277                 if (!strcmp(long_options[option_index].name, "async_start")) {
1278                     async = true;
1279                     traceStop = false;
1280                     traceDump = false;
1281                     g_traceOverwrite = true;
1282                 } else if (!strcmp(long_options[option_index].name, "async_stop")) {
1283                     async = true;
1284                     traceStart = false;
1285                 } else if (!strcmp(long_options[option_index].name, "async_dump")) {
1286                     async = true;
1287                     traceStart = false;
1288                     traceStop = false;
1289                 } else if (!strcmp(long_options[option_index].name, "only_userspace")) {
1290                     onlyUserspace = true;
1291                 } else if (!strcmp(long_options[option_index].name, "stream")) {
1292                     traceStream = true;
1293                     traceDump = false;
1294                 } else if (!strcmp(long_options[option_index].name, "list_categories")) {
1295                     listSupportedCategories();
1296                     exit(0);
1297                 }
1298             break;
1299 
1300             default:
1301                 fprintf(stderr, "\n");
1302                 showHelp(argv[0]);
1303                 exit(-1);
1304             break;
1305         }
1306     }
1307 
1308     if (onlyUserspace) {
1309         if (!async || !(traceStart || traceStop)) {
1310             fprintf(stderr, "--only_userspace can only be used with "
1311                     "--async_start or --async_stop\n");
1312             exit(1);
1313         }
1314     }
1315 
1316     registerSigHandler();
1317 
1318     if (g_initialSleepSecs > 0) {
1319         sleep(g_initialSleepSecs);
1320     }
1321 
1322     bool ok = true;
1323 
1324     if (traceStart) {
1325         ok &= setUpUserspaceTracing();
1326     }
1327 
1328     if (ok && traceStart && !onlyUserspace) {
1329         ok &= setUpKernelTracing();
1330         ok &= setUpVendorTracing();
1331         ok &= startTrace();
1332     }
1333 
1334     if (ok && traceStart) {
1335 
1336         if (!traceStream && !onlyUserspace) {
1337             printf("capturing trace...");
1338             fflush(stdout);
1339         }
1340 
1341         // We clear the trace after starting it because tracing gets enabled for
1342         // each CPU individually in the kernel. Having the beginning of the trace
1343         // contain entries from only one CPU can cause "begin" entries without a
1344         // matching "end" entry to show up if a task gets migrated from one CPU to
1345         // another.
1346         if (!onlyUserspace)
1347             ok = clearTrace();
1348 
1349         writeClockSyncMarker();
1350         if (ok && !async && !traceStream) {
1351             // Sleep to allow the trace to be captured.
1352             struct timespec timeLeft;
1353             timeLeft.tv_sec = g_traceDurationSeconds;
1354             timeLeft.tv_nsec = 0;
1355             do {
1356                 if (g_traceAborted) {
1357                     break;
1358                 }
1359             } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
1360         }
1361 
1362         if (traceStream) {
1363             streamTrace();
1364         }
1365     }
1366 
1367     // Stop the trace and restore the default settings.
1368     if (traceStop && !onlyUserspace)
1369         stopTrace();
1370 
1371     if (ok && traceDump && !onlyUserspace) {
1372         if (!g_traceAborted) {
1373             printf(" done\n");
1374             fflush(stdout);
1375             int outFd = STDOUT_FILENO;
1376             if (g_outputFile) {
1377                 outFd = open(g_outputFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1378             }
1379             if (outFd == -1) {
1380                 printf("Failed to open '%s', err=%d", g_outputFile, errno);
1381             } else {
1382                 dprintf(outFd, "TRACE:\n");
1383                 dumpTrace(outFd);
1384                 if (g_outputFile) {
1385                     close(outFd);
1386                 }
1387             }
1388         } else {
1389             printf("\ntrace aborted.\n");
1390             fflush(stdout);
1391         }
1392         clearTrace();
1393     } else if (!ok) {
1394         fprintf(stderr, "unable to start tracing\n");
1395     }
1396 
1397     // Reset the trace buffer size to 1.
1398     if (traceStop) {
1399         cleanUpUserspaceTracing();
1400         if (!onlyUserspace) {
1401             cleanUpVendorTracing();
1402             cleanUpKernelTracing();
1403         }
1404     }
1405 
1406     return g_traceAborted ? 1 : 0;
1407 }
1408