• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 12
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         { OPT,      "events/gpu_mem/gpu_mem_total/enable" },
104     } },
105     { "input",      "Input",                    ATRACE_TAG_INPUT, { } },
106     { "view",       "View System",              ATRACE_TAG_VIEW, { } },
107     { "webview",    "WebView",                  ATRACE_TAG_WEBVIEW, { } },
108     { "wm",         "Window Manager",           ATRACE_TAG_WINDOW_MANAGER, { } },
109     { "am",         "Activity Manager",         ATRACE_TAG_ACTIVITY_MANAGER, { } },
110     { "sm",         "Sync Manager",             ATRACE_TAG_SYNC_MANAGER, { } },
111     { "audio",      "Audio",                    ATRACE_TAG_AUDIO, { } },
112     { "video",      "Video",                    ATRACE_TAG_VIDEO, { } },
113     { "camera",     "Camera",                   ATRACE_TAG_CAMERA, { } },
114     { "hal",        "Hardware Modules",         ATRACE_TAG_HAL, { } },
115     { "res",        "Resource Loading",         ATRACE_TAG_RESOURCES, { } },
116     { "dalvik",     "Dalvik VM",                ATRACE_TAG_DALVIK, { } },
117     { "rs",         "RenderScript",             ATRACE_TAG_RS, { } },
118     { "bionic",     "Bionic C Library",         ATRACE_TAG_BIONIC, { } },
119     { "power",      "Power Management",         ATRACE_TAG_POWER, { } },
120     { "pm",         "Package Manager",          ATRACE_TAG_PACKAGE_MANAGER, { } },
121     { "ss",         "System Server",            ATRACE_TAG_SYSTEM_SERVER, { } },
122     { "database",   "Database",                 ATRACE_TAG_DATABASE, { } },
123     { "network",    "Network",                  ATRACE_TAG_NETWORK, { } },
124     { "adb",        "ADB",                      ATRACE_TAG_ADB, { } },
125     { "vibrator",   "Vibrator",                 ATRACE_TAG_VIBRATOR, { } },
126     { "aidl",       "AIDL calls",               ATRACE_TAG_AIDL, { } },
127     { "nnapi",      "NNAPI",                    ATRACE_TAG_NNAPI, { } },
128     { "rro",        "Runtime Resource Overlay", ATRACE_TAG_RRO, { } },
129     { k_coreServiceCategory, "Core services", 0, { } },
130     { k_pdxServiceCategory, "PDX services", 0, { } },
131     { "sched",      "CPU Scheduling",   0, {
132         { REQ,      "events/sched/sched_switch/enable" },
133         { REQ,      "events/sched/sched_wakeup/enable" },
134         { OPT,      "events/sched/sched_waking/enable" },
135         { OPT,      "events/sched/sched_blocked_reason/enable" },
136         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
137         { OPT,      "events/sched/sched_pi_setprio/enable" },
138         { OPT,      "events/sched/sched_process_exit/enable" },
139         { OPT,      "events/cgroup/enable" },
140         { OPT,      "events/oom/oom_score_adj_update/enable" },
141         { OPT,      "events/task/task_rename/enable" },
142         { OPT,      "events/task/task_newtask/enable" },
143     } },
144     { "irq",        "IRQ Events",   0, {
145         { REQ,      "events/irq/enable" },
146         { OPT,      "events/ipi/enable" },
147     } },
148     { "irqoff",     "IRQ-disabled code section tracing", 0, {
149         { REQ,      "events/preemptirq/irq_enable/enable" },
150         { REQ,      "events/preemptirq/irq_disable/enable" },
151     } },
152     { "preemptoff", "Preempt-disabled code section tracing", 0, {
153         { REQ,      "events/preemptirq/preempt_enable/enable" },
154         { REQ,      "events/preemptirq/preempt_disable/enable" },
155     } },
156     { "i2c",        "I2C Events",   0, {
157         { REQ,      "events/i2c/enable" },
158         { REQ,      "events/i2c/i2c_read/enable" },
159         { REQ,      "events/i2c/i2c_write/enable" },
160         { REQ,      "events/i2c/i2c_result/enable" },
161         { REQ,      "events/i2c/i2c_reply/enable" },
162         { OPT,      "events/i2c/smbus_read/enable" },
163         { OPT,      "events/i2c/smbus_write/enable" },
164         { OPT,      "events/i2c/smbus_result/enable" },
165         { OPT,      "events/i2c/smbus_reply/enable" },
166     } },
167     { "freq",       "CPU Frequency",    0, {
168         { REQ,      "events/power/cpu_frequency/enable" },
169         { OPT,      "events/power/clock_set_rate/enable" },
170         { OPT,      "events/power/clock_disable/enable" },
171         { OPT,      "events/power/clock_enable/enable" },
172         { OPT,      "events/clk/clk_set_rate/enable" },
173         { OPT,      "events/clk/clk_disable/enable" },
174         { OPT,      "events/clk/clk_enable/enable" },
175         { OPT,      "events/power/cpu_frequency_limits/enable" },
176         { OPT,      "events/power/suspend_resume/enable" },
177         { OPT,      "events/cpuhp/cpuhp_enter/enable" },
178         { OPT,      "events/cpuhp/cpuhp_exit/enable" },
179         { OPT,      "events/cpuhp/cpuhp_pause/enable" },
180     } },
181     { "membus",     "Memory Bus Utilization", 0, {
182         { REQ,      "events/memory_bus/enable" },
183     } },
184     { "idle",       "CPU Idle",         0, {
185         { REQ,      "events/power/cpu_idle/enable" },
186     } },
187     { "disk",       "Disk I/O",         0, {
188         { OPT,      "events/f2fs/f2fs_sync_file_enter/enable" },
189         { OPT,      "events/f2fs/f2fs_sync_file_exit/enable" },
190         { OPT,      "events/f2fs/f2fs_write_begin/enable" },
191         { OPT,      "events/f2fs/f2fs_write_end/enable" },
192         { OPT,      "events/ext4/ext4_da_write_begin/enable" },
193         { OPT,      "events/ext4/ext4_da_write_end/enable" },
194         { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
195         { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
196         { REQ,      "events/block/block_rq_issue/enable" },
197         { REQ,      "events/block/block_rq_complete/enable" },
198     } },
199     { "mmc",        "eMMC commands",    0, {
200         { REQ,      "events/mmc/enable" },
201     } },
202     { "load",       "CPU Load",         0, {
203         { REQ,      "events/cpufreq_interactive/enable" },
204     } },
205     { "sync",       "Synchronization",  0, {
206         // linux kernel < 4.9
207         { OPT,      "events/sync/enable" },
208         // linux kernel == 4.9.x
209         { OPT,      "events/fence/enable" },
210         // linux kernel > 4.9
211         { OPT,      "events/dma_fence/enable" },
212     } },
213     { "workq",      "Kernel Workqueues", 0, {
214         { REQ,      "events/workqueue/enable" },
215     } },
216     { "memreclaim", "Kernel Memory Reclaim", 0, {
217         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
218         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
219         { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
220         { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
221         { OPT,      "events/lowmemorykiller/enable" },
222     } },
223     { "regulators",  "Voltage and Current Regulators", 0, {
224         { REQ,      "events/regulator/enable" },
225     } },
226     { "binder_driver", "Binder Kernel driver", 0, {
227         { REQ,      "events/binder/binder_transaction/enable" },
228         { REQ,      "events/binder/binder_transaction_received/enable" },
229         { REQ,      "events/binder/binder_transaction_alloc_buf/enable" },
230         { OPT,      "events/binder/binder_set_priority/enable" },
231     } },
232     { "binder_lock", "Binder global lock trace", 0, {
233         { OPT,      "events/binder/binder_lock/enable" },
234         { OPT,      "events/binder/binder_locked/enable" },
235         { OPT,      "events/binder/binder_unlock/enable" },
236     } },
237     { "pagecache",  "Page cache", 0, {
238         { REQ,      "events/filemap/enable" },
239     } },
240     { "memory",  "Memory", 0, {
241         { OPT,      "events/mm_event/mm_event_record/enable" },
242         { OPT,      "events/kmem/rss_stat/enable" },
243         { OPT,      "events/kmem/ion_heap_grow/enable" },
244         { OPT,      "events/kmem/ion_heap_shrink/enable" },
245         { OPT,      "events/ion/ion_stat/enable" },
246         { OPT,      "events/gpu_mem/gpu_mem_total/enable" },
247     } },
248     { "thermal",  "Thermal event", 0, {
249         { REQ,      "events/thermal/thermal_temperature/enable" },
250         { OPT,      "events/thermal/cdev_update/enable" },
251     } },
252 };
253 
254 struct TracingVendorCategory {
255     // The name identifying the category.
256     std::string name;
257 
258     // A longer description of the category.
259     std::string description;
260 
261     // If the category is enabled through command.
262     bool enabled;
263 
TracingVendorCategoryTracingVendorCategory264     TracingVendorCategory(string &&name, string &&description, bool enabled)
265             : name(std::move(name))
266             , description(std::move(description))
267             , enabled(enabled)
268     {}
269 };
270 
271 /* Command line options */
272 static int g_traceDurationSeconds = 5;
273 static bool g_traceOverwrite = false;
274 static int g_traceBufferSizeKB = 2048;
275 static bool g_compress = false;
276 static bool g_nohup = false;
277 static int g_initialSleepSecs = 0;
278 static const char* g_categoriesFile = nullptr;
279 static const char* g_kernelTraceFuncs = nullptr;
280 static const char* g_debugAppCmdLine = "";
281 static const char* g_outputFile = nullptr;
282 
283 /* Global state */
284 static bool g_tracePdx = false;
285 static bool g_traceAborted = false;
286 static bool g_categoryEnables[arraysize(k_categories)] = {};
287 static std::string g_traceFolder;
288 static sp<IAtraceDevice> g_atraceHal;
289 static std::vector<TracingVendorCategory> g_vendorCategories;
290 
291 /* Sys file paths */
292 static const char* k_traceClockPath =
293     "trace_clock";
294 
295 static const char* k_traceBufferSizePath =
296     "buffer_size_kb";
297 
298 #if 0
299 // TODO: Re-enable after stabilization
300 static const char* k_traceCmdlineSizePath =
301     "saved_cmdlines_size";
302 #endif
303 
304 static const char* k_tracingOverwriteEnablePath =
305     "options/overwrite";
306 
307 static const char* k_currentTracerPath =
308     "current_tracer";
309 
310 static const char* k_printTgidPath =
311     "options/print-tgid";
312 
313 static const char* k_recordTgidPath =
314     "options/record-tgid";
315 
316 static const char* k_funcgraphAbsTimePath =
317     "options/funcgraph-abstime";
318 
319 static const char* k_funcgraphCpuPath =
320     "options/funcgraph-cpu";
321 
322 static const char* k_funcgraphProcPath =
323     "options/funcgraph-proc";
324 
325 static const char* k_ftraceFilterPath =
326     "set_ftrace_filter";
327 
328 static const char* k_tracingOnPath =
329     "tracing_on";
330 
331 static const char* k_tracePath =
332     "trace";
333 
334 static const char* k_traceStreamPath =
335     "trace_pipe";
336 
337 static const char* k_traceMarkerPath =
338     "trace_marker";
339 
340 // Check whether a file exists.
fileExists(const char * filename)341 static bool fileExists(const char* filename) {
342     return access((g_traceFolder + filename).c_str(), F_OK) != -1;
343 }
344 
345 // Check whether a file is writable.
fileIsWritable(const char * filename)346 static bool fileIsWritable(const char* filename) {
347     return access((g_traceFolder + filename).c_str(), W_OK) != -1;
348 }
349 
350 // Truncate a file.
truncateFile(const char * path)351 static bool truncateFile(const char* path)
352 {
353     // This uses creat rather than truncate because some of the debug kernel
354     // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
355     // calls to truncate, but they are cleared by calls to creat.
356     int traceFD = creat((g_traceFolder + path).c_str(), 0);
357     if (traceFD == -1) {
358         fprintf(stderr, "error truncating %s: %s (%d)\n", (g_traceFolder + path).c_str(),
359             strerror(errno), errno);
360         return false;
361     }
362 
363     close(traceFD);
364 
365     return true;
366 }
367 
_writeStr(const char * filename,const char * str,int flags)368 static bool _writeStr(const char* filename, const char* str, int flags)
369 {
370     std::string fullFilename = g_traceFolder + filename;
371     int fd = open(fullFilename.c_str(), flags);
372     if (fd == -1) {
373         fprintf(stderr, "error opening %s: %s (%d)\n", fullFilename.c_str(),
374                 strerror(errno), errno);
375         return false;
376     }
377 
378     bool ok = true;
379     ssize_t len = strlen(str);
380     if (write(fd, str, len) != len) {
381         fprintf(stderr, "error writing to %s: %s (%d)\n", fullFilename.c_str(),
382                 strerror(errno), errno);
383         ok = false;
384     }
385 
386     close(fd);
387 
388     return ok;
389 }
390 
391 // Write a string to a file, returning true if the write was successful.
writeStr(const char * filename,const char * str)392 static bool writeStr(const char* filename, const char* str)
393 {
394     return _writeStr(filename, str, O_WRONLY);
395 }
396 
397 // Append a string to a file, returning true if the write was successful.
appendStr(const char * filename,const char * str)398 static bool appendStr(const char* filename, const char* str)
399 {
400     return _writeStr(filename, str, O_APPEND|O_WRONLY);
401 }
402 
writeClockSyncMarker()403 static void writeClockSyncMarker()
404 {
405   char buffer[128];
406   int len = 0;
407   int fd = open((g_traceFolder + k_traceMarkerPath).c_str(), O_WRONLY);
408   if (fd == -1) {
409       fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
410               strerror(errno), errno);
411       return;
412   }
413   float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
414 
415   len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
416   if (write(fd, buffer, len) != len) {
417       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
418   }
419 
420   int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
421   len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
422   if (write(fd, buffer, len) != len) {
423       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
424   }
425 
426   close(fd);
427 }
428 
429 // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
430 // file.
setKernelOptionEnable(const char * filename,bool enable)431 static bool setKernelOptionEnable(const char* filename, bool enable)
432 {
433     return writeStr(filename, enable ? "1" : "0");
434 }
435 
436 // Check whether the category is supported on the device with the current
437 // rootness.  A category is supported only if all its required /sys/ files are
438 // writable and if enabling the category will enable one or more tracing tags
439 // or /sys/ files.
isCategorySupported(const TracingCategory & category)440 static bool isCategorySupported(const TracingCategory& category)
441 {
442     if (strcmp(category.name, k_coreServiceCategory) == 0) {
443         return !android::base::GetProperty(k_coreServicesProp, "").empty();
444     }
445 
446     if (strcmp(category.name, k_pdxServiceCategory) == 0) {
447         return true;
448     }
449 
450     bool ok = category.tags != 0;
451     for (int i = 0; i < MAX_SYS_FILES; i++) {
452         const char* path = category.sysfiles[i].path;
453         bool req = category.sysfiles[i].required == REQ;
454         if (path != nullptr) {
455             if (fileIsWritable(path)) {
456                 ok = true;
457             } else if (req) {
458                 return false;
459             }
460         }
461     }
462     return ok;
463 }
464 
465 // Check whether the category would be supported on the device if the user
466 // were root.  This function assumes that root is able to write to any file
467 // that exists.  It performs the same logic as isCategorySupported, but it
468 // uses file existence rather than writability in the /sys/ file checks.
isCategorySupportedForRoot(const TracingCategory & category)469 static bool isCategorySupportedForRoot(const TracingCategory& category)
470 {
471     bool ok = category.tags != 0;
472     for (int i = 0; i < MAX_SYS_FILES; i++) {
473         const char* path = category.sysfiles[i].path;
474         bool req = category.sysfiles[i].required == REQ;
475         if (path != nullptr) {
476             if (req) {
477                 if (!fileExists(path)) {
478                     return false;
479                 } else {
480                     ok = true;
481                 }
482             } else {
483                 ok |= fileExists(path);
484             }
485         }
486     }
487     return ok;
488 }
489 
490 // Enable or disable overwriting of the kernel trace buffers.  Disabling this
491 // will cause tracing to stop once the trace buffers have filled up.
setTraceOverwriteEnable(bool enable)492 static bool setTraceOverwriteEnable(bool enable)
493 {
494     return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
495 }
496 
497 // Set the user initiated trace property
setUserInitiatedTraceProperty(bool enable)498 static bool setUserInitiatedTraceProperty(bool enable)
499 {
500     if (!android::base::SetProperty(k_userInitiatedTraceProperty, enable ? "1" : "")) {
501         fprintf(stderr, "error setting user initiated strace system property\n");
502         return false;
503     }
504     return true;
505 }
506 
507 // Enable or disable kernel tracing.
setTracingEnabled(bool enable)508 static bool setTracingEnabled(bool enable)
509 {
510     return setKernelOptionEnable(k_tracingOnPath, enable);
511 }
512 
513 // Clear the contents of the kernel trace.
clearTrace()514 static bool clearTrace()
515 {
516     return truncateFile(k_tracePath);
517 }
518 
519 // Set the size of the kernel's trace buffer in kilobytes.
setTraceBufferSizeKB(int size)520 static bool setTraceBufferSizeKB(int size)
521 {
522     char str[32] = "1";
523     if (size < 1) {
524         size = 1;
525     }
526     snprintf(str, 32, "%d", size);
527     return writeStr(k_traceBufferSizePath, str);
528 }
529 
530 #if 0
531 // TODO: Re-enable after stabilization
532 // Set the default size of cmdline hashtable
533 static bool setCmdlineSize()
534 {
535     if (fileExists(k_traceCmdlineSizePath)) {
536         return writeStr(k_traceCmdlineSizePath, "8192");
537     }
538     return true;
539 }
540 #endif
541 
542 // Set the clock to the best available option while tracing. Use 'boot' if it's
543 // available; otherwise, use 'mono'. If neither are available use 'global'.
544 // Any write to the trace_clock sysfs file will reset the buffer, so only
545 // update it if the requested value is not the current value.
setClock()546 static bool setClock()
547 {
548     std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
549     std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
550         std::istreambuf_iterator<char>());
551 
552     std::string newClock;
553     if (clockStr.find("boot") != std::string::npos) {
554         newClock = "boot";
555     } else if (clockStr.find("mono") != std::string::npos) {
556         newClock = "mono";
557     } else {
558         newClock = "global";
559     }
560 
561     size_t begin = clockStr.find('[') + 1;
562     size_t end = clockStr.find(']');
563     if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
564         return true;
565     }
566     return writeStr(k_traceClockPath, newClock.c_str());
567 }
568 
setPrintTgidEnableIfPresent(bool enable)569 static bool setPrintTgidEnableIfPresent(bool enable)
570 {
571     // Pre-4.13 this was options/print-tgid as an android-specific option.
572     // In 4.13+ this is an upstream option called options/record-tgid
573     // Both options produce the same ftrace format change
574     if (fileExists(k_printTgidPath)) {
575         return setKernelOptionEnable(k_printTgidPath, enable);
576     }
577     if (fileExists(k_recordTgidPath)) {
578         return setKernelOptionEnable(k_recordTgidPath, enable);
579     }
580     return true;
581 }
582 
583 // Set the trace tags that userland tracing uses, and poke the running
584 // processes to pick up the new value.
setTagsProperty(uint64_t tags)585 static bool setTagsProperty(uint64_t tags)
586 {
587     std::string value = android::base::StringPrintf("%#" PRIx64, tags);
588     if (!android::base::SetProperty(k_traceTagsProperty, value)) {
589         fprintf(stderr, "error setting trace tags system property\n");
590         return false;
591     }
592     return true;
593 }
594 
clearAppProperties()595 static void clearAppProperties()
596 {
597     if (!android::base::SetProperty(k_traceAppsNumberProperty, "")) {
598         fprintf(stderr, "failed to clear system property: %s",
599               k_traceAppsNumberProperty);
600     }
601 }
602 
603 // Set the system property that indicates which apps should perform
604 // application-level tracing.
setAppCmdlineProperty(char * cmdline)605 static bool setAppCmdlineProperty(char* cmdline)
606 {
607     int i = 0;
608     char* start = cmdline;
609     while (start != nullptr) {
610         char* end = strchr(start, ',');
611         if (end != nullptr) {
612             *end = '\0';
613             end++;
614         }
615         std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
616         if (!android::base::SetProperty(key, start)) {
617             fprintf(stderr, "error setting trace app %d property to %s\n", i, key.c_str());
618             clearAppProperties();
619             return false;
620         }
621         start = end;
622         i++;
623     }
624 
625     std::string value = android::base::StringPrintf("%d", i);
626     if (!android::base::SetProperty(k_traceAppsNumberProperty, value)) {
627         fprintf(stderr, "error setting trace app number property to %s\n", value.c_str());
628         clearAppProperties();
629         return false;
630     }
631     return true;
632 }
633 
634 // Disable all /sys/ enable files.
disableKernelTraceEvents()635 static bool disableKernelTraceEvents() {
636     bool ok = true;
637     for (size_t i = 0; i < arraysize(k_categories); i++) {
638         const TracingCategory &c = k_categories[i];
639         for (int j = 0; j < MAX_SYS_FILES; j++) {
640             const char* path = c.sysfiles[j].path;
641             if (path != nullptr && fileIsWritable(path)) {
642                 ok &= setKernelOptionEnable(path, false);
643             }
644         }
645     }
646     return ok;
647 }
648 
649 // Verify that the comma separated list of functions are being traced by the
650 // kernel.
verifyKernelTraceFuncs(const char * funcs)651 static bool verifyKernelTraceFuncs(const char* funcs)
652 {
653     std::string buf;
654     if (!android::base::ReadFileToString(g_traceFolder + k_ftraceFilterPath, &buf)) {
655          fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
656             strerror(errno), errno);
657          return false;
658     }
659 
660     String8 funcList = String8::format("\n%s",buf.c_str());
661 
662     // Make sure that every function listed in funcs is in the list we just
663     // read from the kernel, except for wildcard inputs.
664     bool ok = true;
665     char* myFuncs = strdup(funcs);
666     char* func = strtok(myFuncs, ",");
667     while (func) {
668         if (!strchr(func, '*')) {
669             String8 fancyFunc = String8::format("\n%s\n", func);
670             bool found = funcList.find(fancyFunc.string(), 0) >= 0;
671             if (!found || func[0] == '\0') {
672                 fprintf(stderr, "error: \"%s\" is not a valid kernel function "
673                         "to trace.\n", func);
674                 ok = false;
675             }
676         }
677         func = strtok(nullptr, ",");
678     }
679     free(myFuncs);
680     return ok;
681 }
682 
683 // Set the comma separated list of functions that the kernel is to trace.
setKernelTraceFuncs(const char * funcs)684 static bool setKernelTraceFuncs(const char* funcs)
685 {
686     bool ok = true;
687 
688     if (funcs == nullptr || funcs[0] == '\0') {
689         // Disable kernel function tracing.
690         if (fileIsWritable(k_currentTracerPath)) {
691             ok &= writeStr(k_currentTracerPath, "nop");
692         }
693         if (fileIsWritable(k_ftraceFilterPath)) {
694             ok &= truncateFile(k_ftraceFilterPath);
695         }
696     } else {
697         // Enable kernel function tracing.
698         ok &= writeStr(k_currentTracerPath, "function_graph");
699         ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
700         ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
701         ok &= setKernelOptionEnable(k_funcgraphProcPath, 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