atrace.cpp revision aa51c8c56f61e6727b80d5ab3d67210b4a4f403b
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 <sys/sendfile.h>
30#include <time.h>
31#include <unistd.h>
32#include <zlib.h>
33
34#include <memory>
35
36#include <binder/IBinder.h>
37#include <binder/IServiceManager.h>
38#include <binder/Parcel.h>
39
40#include <android/hidl/manager/1.0/IServiceManager.h>
41#include <hidl/ServiceManagement.h>
42#include <cutils/properties.h>
43
44#include <utils/String8.h>
45#include <utils/Timers.h>
46#include <utils/Tokenizer.h>
47#include <utils/Trace.h>
48#include <android-base/file.h>
49
50using namespace android;
51
52using std::string;
53#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
54
55#define MAX_SYS_FILES 10
56#define MAX_PACKAGES 16
57
58const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
59
60const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
61const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
62const char* k_coreServiceCategory = "core_services";
63const char* k_coreServicesProp = "ro.atrace.core.services";
64
65typedef enum { OPT, REQ } requiredness  ;
66
67struct TracingCategory {
68    // The name identifying the category.
69    const char* name;
70
71    // A longer description of the category.
72    const char* longname;
73
74    // The userland tracing tags that the category enables.
75    uint64_t tags;
76
77    // The fname==NULL terminated list of /sys/ files that the category
78    // enables.
79    struct {
80        // Whether the file must be writable in order to enable the tracing
81        // category.
82        requiredness required;
83
84        // The path to the enable file.
85        const char* path;
86    } sysfiles[MAX_SYS_FILES];
87};
88
89/* Tracing categories */
90static const TracingCategory k_categories[] = {
91    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, { } },
92    { "input",      "Input",            ATRACE_TAG_INPUT, { } },
93    { "view",       "View System",      ATRACE_TAG_VIEW, { } },
94    { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
95    { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
96    { "am",         "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
97    { "sm",         "Sync Manager",     ATRACE_TAG_SYNC_MANAGER, { } },
98    { "audio",      "Audio",            ATRACE_TAG_AUDIO, { } },
99    { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
100    { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
101    { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
102    { "app",        "Application",      ATRACE_TAG_APP, { } },
103    { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
104    { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
105    { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
106    { "bionic",     "Bionic C Library", ATRACE_TAG_BIONIC, { } },
107    { "power",      "Power Management", ATRACE_TAG_POWER, { } },
108    { "pm",         "Package Manager",  ATRACE_TAG_PACKAGE_MANAGER, { } },
109    { "ss",         "System Server",    ATRACE_TAG_SYSTEM_SERVER, { } },
110    { "database",   "Database",         ATRACE_TAG_DATABASE, { } },
111    { "network",    "Network",          ATRACE_TAG_NETWORK, { } },
112    { k_coreServiceCategory, "Core services", 0, { } },
113    { "sched",      "CPU Scheduling",   0, {
114        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
115        { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
116        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable" },
117        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable" },
118    } },
119    { "irq",        "IRQ Events",   0, {
120        { REQ,      "/sys/kernel/debug/tracing/events/irq/enable" },
121        { OPT,      "/sys/kernel/debug/tracing/events/ipi/enable" },
122    } },
123    { "freq",       "CPU Frequency",    0, {
124        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
125        { OPT,      "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
126        { OPT,      "/sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable" },
127    } },
128    { "membus",     "Memory Bus Utilization", 0, {
129        { REQ,      "/sys/kernel/debug/tracing/events/memory_bus/enable" },
130    } },
131    { "idle",       "CPU Idle",         0, {
132        { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_idle/enable" },
133    } },
134    { "disk",       "Disk I/O",         0, {
135        { OPT,      "/sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable" },
136        { OPT,      "/sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable" },
137        { OPT,      "/sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable" },
138        { OPT,      "/sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable" },
139        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable" },
140        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable" },
141        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable" },
142        { OPT,      "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable" },
143        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable" },
144        { REQ,      "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable" },
145    } },
146    { "mmc",        "eMMC commands",    0, {
147        { REQ,      "/sys/kernel/debug/tracing/events/mmc/enable" },
148    } },
149    { "load",       "CPU Load",         0, {
150        { REQ,      "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable" },
151    } },
152    { "sync",       "Synchronization",  0, {
153        { REQ,      "/sys/kernel/debug/tracing/events/sync/enable" },
154    } },
155    { "workq",      "Kernel Workqueues", 0, {
156        { REQ,      "/sys/kernel/debug/tracing/events/workqueue/enable" },
157    } },
158    { "memreclaim", "Kernel Memory Reclaim", 0, {
159        { REQ,      "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
160        { REQ,      "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
161        { REQ,      "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable" },
162        { REQ,      "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable" },
163    } },
164    { "regulators",  "Voltage and Current Regulators", 0, {
165        { REQ,      "/sys/kernel/debug/tracing/events/regulator/enable" },
166    } },
167    { "binder_driver", "Binder Kernel driver", 0, {
168        { REQ,      "/sys/kernel/debug/tracing/events/binder/binder_transaction/enable" },
169        { REQ,      "/sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable" },
170    } },
171    { "binder_lock", "Binder global lock trace", 0, {
172        { REQ,      "/sys/kernel/debug/tracing/events/binder/binder_lock/enable" },
173        { REQ,      "/sys/kernel/debug/tracing/events/binder/binder_locked/enable" },
174        { REQ,      "/sys/kernel/debug/tracing/events/binder/binder_unlock/enable" },
175    } },
176    { "pagecache",  "Page cache", 0, {
177        { REQ,      "/sys/kernel/debug/tracing/events/filemap/enable" },
178    } },
179};
180
181/* Command line options */
182static int g_traceDurationSeconds = 5;
183static bool g_traceOverwrite = false;
184static int g_traceBufferSizeKB = 2048;
185static bool g_compress = false;
186static bool g_nohup = false;
187static int g_initialSleepSecs = 0;
188static const char* g_categoriesFile = NULL;
189static const char* g_kernelTraceFuncs = NULL;
190static const char* g_debugAppCmdLine = "";
191static const char* g_outputFile = nullptr;
192
193/* Global state */
194static bool g_traceAborted = false;
195static bool g_categoryEnables[NELEM(k_categories)] = {};
196
197/* Sys file paths */
198static const char* k_traceClockPath =
199    "/sys/kernel/debug/tracing/trace_clock";
200
201static const char* k_traceBufferSizePath =
202    "/sys/kernel/debug/tracing/buffer_size_kb";
203
204static const char* k_tracingOverwriteEnablePath =
205    "/sys/kernel/debug/tracing/options/overwrite";
206
207static const char* k_currentTracerPath =
208    "/sys/kernel/debug/tracing/current_tracer";
209
210static const char* k_printTgidPath =
211    "/sys/kernel/debug/tracing/options/print-tgid";
212
213static const char* k_funcgraphAbsTimePath =
214    "/sys/kernel/debug/tracing/options/funcgraph-abstime";
215
216static const char* k_funcgraphCpuPath =
217    "/sys/kernel/debug/tracing/options/funcgraph-cpu";
218
219static const char* k_funcgraphProcPath =
220    "/sys/kernel/debug/tracing/options/funcgraph-proc";
221
222static const char* k_funcgraphFlatPath =
223    "/sys/kernel/debug/tracing/options/funcgraph-flat";
224
225static const char* k_funcgraphDurationPath =
226    "/sys/kernel/debug/tracing/options/funcgraph-duration";
227
228static const char* k_ftraceFilterPath =
229    "/sys/kernel/debug/tracing/set_ftrace_filter";
230
231static const char* k_tracingOnPath =
232    "/sys/kernel/debug/tracing/tracing_on";
233
234static const char* k_tracePath =
235    "/sys/kernel/debug/tracing/trace";
236
237static const char* k_traceStreamPath =
238    "/sys/kernel/debug/tracing/trace_pipe";
239
240static const char* k_traceMarkerPath =
241    "/sys/kernel/debug/tracing/trace_marker";
242
243// Check whether a file exists.
244static bool fileExists(const char* filename) {
245    return access(filename, F_OK) != -1;
246}
247
248// Check whether a file is writable.
249static bool fileIsWritable(const char* filename) {
250    return access(filename, W_OK) != -1;
251}
252
253// Truncate a file.
254static bool truncateFile(const char* path)
255{
256    // This uses creat rather than truncate because some of the debug kernel
257    // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
258    // calls to truncate, but they are cleared by calls to creat.
259    int traceFD = creat(path, 0);
260    if (traceFD == -1) {
261        fprintf(stderr, "error truncating %s: %s (%d)\n", path,
262            strerror(errno), errno);
263        return false;
264    }
265
266    close(traceFD);
267
268    return true;
269}
270
271static bool _writeStr(const char* filename, const char* str, int flags)
272{
273    int fd = open(filename, flags);
274    if (fd == -1) {
275        fprintf(stderr, "error opening %s: %s (%d)\n", filename,
276                strerror(errno), errno);
277        return false;
278    }
279
280    bool ok = true;
281    ssize_t len = strlen(str);
282    if (write(fd, str, len) != len) {
283        fprintf(stderr, "error writing to %s: %s (%d)\n", filename,
284                strerror(errno), errno);
285        ok = false;
286    }
287
288    close(fd);
289
290    return ok;
291}
292
293// Write a string to a file, returning true if the write was successful.
294static bool writeStr(const char* filename, const char* str)
295{
296    return _writeStr(filename, str, O_WRONLY);
297}
298
299// Append a string to a file, returning true if the write was successful.
300static bool appendStr(const char* filename, const char* str)
301{
302    return _writeStr(filename, str, O_APPEND|O_WRONLY);
303}
304
305static void writeClockSyncMarker()
306{
307  char buffer[128];
308  int len = 0;
309  int fd = open(k_traceMarkerPath, O_WRONLY);
310  if (fd == -1) {
311      fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
312              strerror(errno), errno);
313      return;
314  }
315  float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
316
317  len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
318  if (write(fd, buffer, len) != len) {
319      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
320  }
321
322  int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
323  len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
324  if (write(fd, buffer, len) != len) {
325      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
326  }
327
328  close(fd);
329}
330
331// Enable or disable a kernel option by writing a "1" or a "0" into a /sys
332// file.
333static bool setKernelOptionEnable(const char* filename, bool enable)
334{
335    return writeStr(filename, enable ? "1" : "0");
336}
337
338// Check whether the category is supported on the device with the current
339// rootness.  A category is supported only if all its required /sys/ files are
340// writable and if enabling the category will enable one or more tracing tags
341// or /sys/ files.
342static bool isCategorySupported(const TracingCategory& category)
343{
344    if (strcmp(category.name, k_coreServiceCategory) == 0) {
345        char value[PROPERTY_VALUE_MAX];
346        property_get(k_coreServicesProp, value, "");
347        return strlen(value) != 0;
348    }
349
350    bool ok = category.tags != 0;
351    for (int i = 0; i < MAX_SYS_FILES; i++) {
352        const char* path = category.sysfiles[i].path;
353        bool req = category.sysfiles[i].required == REQ;
354        if (path != NULL) {
355            if (req) {
356                if (!fileIsWritable(path)) {
357                    return false;
358                } else {
359                    ok = true;
360                }
361            } else {
362                ok |= fileIsWritable(path);
363            }
364        }
365    }
366    return ok;
367}
368
369// Check whether the category would be supported on the device if the user
370// were root.  This function assumes that root is able to write to any file
371// that exists.  It performs the same logic as isCategorySupported, but it
372// uses file existance rather than writability in the /sys/ file checks.
373static bool isCategorySupportedForRoot(const TracingCategory& category)
374{
375    bool ok = category.tags != 0;
376    for (int i = 0; i < MAX_SYS_FILES; i++) {
377        const char* path = category.sysfiles[i].path;
378        bool req = category.sysfiles[i].required == REQ;
379        if (path != NULL) {
380            if (req) {
381                if (!fileExists(path)) {
382                    return false;
383                } else {
384                    ok = true;
385                }
386            } else {
387                ok |= fileExists(path);
388            }
389        }
390    }
391    return ok;
392}
393
394// Enable or disable overwriting of the kernel trace buffers.  Disabling this
395// will cause tracing to stop once the trace buffers have filled up.
396static bool setTraceOverwriteEnable(bool enable)
397{
398    return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
399}
400
401// Enable or disable kernel tracing.
402static bool setTracingEnabled(bool enable)
403{
404    return setKernelOptionEnable(k_tracingOnPath, enable);
405}
406
407// Clear the contents of the kernel trace.
408static bool clearTrace()
409{
410    return truncateFile(k_tracePath);
411}
412
413// Set the size of the kernel's trace buffer in kilobytes.
414static bool setTraceBufferSizeKB(int size)
415{
416    char str[32] = "1";
417    int len;
418    if (size < 1) {
419        size = 1;
420    }
421    snprintf(str, 32, "%d", size);
422    return writeStr(k_traceBufferSizePath, str);
423}
424
425// Read the trace_clock sysfs file and return true if it matches the requested
426// value.  The trace_clock file format is:
427// local [global] counter uptime perf
428static bool isTraceClock(const char *mode)
429{
430    int fd = open(k_traceClockPath, O_RDONLY);
431    if (fd == -1) {
432        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
433            strerror(errno), errno);
434        return false;
435    }
436
437    char buf[4097];
438    ssize_t n = read(fd, buf, 4096);
439    close(fd);
440    if (n == -1) {
441        fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
442            strerror(errno), errno);
443        return false;
444    }
445    buf[n] = '\0';
446
447    char *start = strchr(buf, '[');
448    if (start == NULL) {
449        return false;
450    }
451    start++;
452
453    char *end = strchr(start, ']');
454    if (end == NULL) {
455        return false;
456    }
457    *end = '\0';
458
459    return strcmp(mode, start) == 0;
460}
461
462// Enable or disable the kernel's use of the global clock.  Disabling the global
463// clock will result in the kernel using a per-CPU local clock.
464// Any write to the trace_clock sysfs file will reset the buffer, so only
465// update it if the requested value is not the current value.
466static bool setGlobalClockEnable(bool enable)
467{
468    const char *clock = enable ? "global" : "local";
469
470    if (isTraceClock(clock)) {
471        return true;
472    }
473
474    return writeStr(k_traceClockPath, clock);
475}
476
477static bool setPrintTgidEnableIfPresent(bool enable)
478{
479    if (fileExists(k_printTgidPath)) {
480        return setKernelOptionEnable(k_printTgidPath, enable);
481    }
482    return true;
483}
484
485// Poke all the binder-enabled processes in the system to get them to re-read
486// their system properties.
487static bool pokeBinderServices()
488{
489    sp<IServiceManager> sm = defaultServiceManager();
490    Vector<String16> services = sm->listServices();
491    for (size_t i = 0; i < services.size(); i++) {
492        sp<IBinder> obj = sm->checkService(services[i]);
493        if (obj != NULL) {
494            Parcel data;
495            if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data,
496                    NULL, 0) != OK) {
497                if (false) {
498                    // XXX: For some reason this fails on tablets trying to
499                    // poke the "phone" service.  It's not clear whether some
500                    // are expected to fail.
501                    String8 svc(services[i]);
502                    fprintf(stderr, "error poking binder service %s\n",
503                        svc.string());
504                    return false;
505                }
506            }
507        }
508    }
509    return true;
510}
511
512// Poke all the HAL processes in the system to get them to re-read
513// their system properties.
514static void pokeHalServices()
515{
516    using ::android::hidl::manager::V1_0::IServiceManager;
517    using ::android::hardware::IBinder;
518    using ::android::hardware::hidl_string;
519    using ::android::hardware::Parcel;
520
521    Parcel data;
522
523    sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
524    auto listRet = sm->list([&](const auto &interfaces) {
525        for (size_t i = 0; i < interfaces.size(); i++) {
526            string fqInstanceName = interfaces[i];
527            string::size_type n = fqInstanceName.find("/");
528            if (n == std::string::npos || interfaces[i].size() == n+1)
529                continue;
530            hidl_string fqInterfaceName = fqInstanceName.substr(0, n);
531            hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos);
532            auto getRet = sm->get(fqInterfaceName, instanceName, [&](const auto &interface) {
533                // TODO(b/32756130)
534                // Once IServiceManager returns IBase, use interface->notifySyspropsChanged() here
535                interface->transact(IBinder::SYSPROPS_TRANSACTION, data, nullptr, 0, nullptr);
536            });
537            if (!getRet.isOk()) {
538                fprintf(stderr, "failed to get service %s: %s\n",
539                        fqInstanceName.c_str(),
540                        getRet.getStatus().toString8().string());
541            }
542        }
543    });
544    if (!listRet.isOk()) {
545        fprintf(stderr, "failed to list services: %s\n", listRet.getStatus().toString8().string());
546    }
547}
548
549// Set the trace tags that userland tracing uses, and poke the running
550// processes to pick up the new value.
551static bool setTagsProperty(uint64_t tags)
552{
553    char buf[PROPERTY_VALUE_MAX];
554    snprintf(buf, sizeof(buf), "%#" PRIx64, tags);
555    if (property_set(k_traceTagsProperty, buf) < 0) {
556        fprintf(stderr, "error setting trace tags system property\n");
557        return false;
558    }
559    return true;
560}
561
562static void clearAppProperties()
563{
564    char buf[PROPERTY_KEY_MAX];
565    for (int i = 0; i < MAX_PACKAGES; i++) {
566        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
567        if (property_set(buf, "") < 0) {
568            fprintf(stderr, "failed to clear system property: %s\n", buf);
569        }
570    }
571    if (property_set(k_traceAppsNumberProperty, "") < 0) {
572        fprintf(stderr, "failed to clear system property: %s",
573              k_traceAppsNumberProperty);
574    }
575}
576
577// Set the system property that indicates which apps should perform
578// application-level tracing.
579static bool setAppCmdlineProperty(char* cmdline)
580{
581    char buf[PROPERTY_KEY_MAX];
582    int i = 0;
583    char* start = cmdline;
584    while (start != NULL) {
585        if (i == MAX_PACKAGES) {
586            fprintf(stderr, "error: only 16 packages could be traced at once\n");
587            clearAppProperties();
588            return false;
589        }
590        char* end = strchr(start, ',');
591        if (end != NULL) {
592            *end = '\0';
593            end++;
594        }
595        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
596        if (property_set(buf, start) < 0) {
597            fprintf(stderr, "error setting trace app %d property to %s\n", i, buf);
598            clearAppProperties();
599            return false;
600        }
601        start = end;
602        i++;
603    }
604
605    snprintf(buf, sizeof(buf), "%d", i);
606    if (property_set(k_traceAppsNumberProperty, buf) < 0) {
607        fprintf(stderr, "error setting trace app number property to %s\n", buf);
608        clearAppProperties();
609        return false;
610    }
611    return true;
612}
613
614// Disable all /sys/ enable files.
615static bool disableKernelTraceEvents() {
616    bool ok = true;
617    for (int i = 0; i < NELEM(k_categories); i++) {
618        const TracingCategory &c = k_categories[i];
619        for (int j = 0; j < MAX_SYS_FILES; j++) {
620            const char* path = c.sysfiles[j].path;
621            if (path != NULL && fileIsWritable(path)) {
622                ok &= setKernelOptionEnable(path, false);
623            }
624        }
625    }
626    return ok;
627}
628
629// Verify that the comma separated list of functions are being traced by the
630// kernel.
631static bool verifyKernelTraceFuncs(const char* funcs)
632{
633    std::string buf;
634    if (!android::base::ReadFileToString(k_ftraceFilterPath, &buf)) {
635         fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
636            strerror(errno), errno);
637         return false;
638    }
639
640    String8 funcList = String8::format("\n%s",buf.c_str());
641
642    // Make sure that every function listed in funcs is in the list we just
643    // read from the kernel, except for wildcard inputs.
644    bool ok = true;
645    char* myFuncs = strdup(funcs);
646    char* func = strtok(myFuncs, ",");
647    while (func) {
648        if (!strchr(func, '*')) {
649            String8 fancyFunc = String8::format("\n%s\n", func);
650            bool found = funcList.find(fancyFunc.string(), 0) >= 0;
651            if (!found || func[0] == '\0') {
652                fprintf(stderr, "error: \"%s\" is not a valid kernel function "
653                        "to trace.\n", func);
654                ok = false;
655            }
656        }
657        func = strtok(NULL, ",");
658    }
659    free(myFuncs);
660    return ok;
661}
662
663// Set the comma separated list of functions that the kernel is to trace.
664static bool setKernelTraceFuncs(const char* funcs)
665{
666    bool ok = true;
667
668    if (funcs == NULL || funcs[0] == '\0') {
669        // Disable kernel function tracing.
670        if (fileIsWritable(k_currentTracerPath)) {
671            ok &= writeStr(k_currentTracerPath, "nop");
672        }
673        if (fileIsWritable(k_ftraceFilterPath)) {
674            ok &= truncateFile(k_ftraceFilterPath);
675        }
676    } else {
677        // Enable kernel function tracing.
678        ok &= writeStr(k_currentTracerPath, "function_graph");
679        ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
680        ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
681        ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
682        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
683
684        // Set the requested filter functions.
685        ok &= truncateFile(k_ftraceFilterPath);
686        char* myFuncs = strdup(funcs);
687        char* func = strtok(myFuncs, ",");
688        while (func) {
689            ok &= appendStr(k_ftraceFilterPath, func);
690            func = strtok(NULL, ",");
691        }
692        free(myFuncs);
693
694        // Verify that the set functions are being traced.
695        if (ok) {
696            ok &= verifyKernelTraceFuncs(funcs);
697        }
698    }
699
700    return ok;
701}
702
703static bool setCategoryEnable(const char* name, bool enable)
704{
705    for (int i = 0; i < NELEM(k_categories); i++) {
706        const TracingCategory& c = k_categories[i];
707        if (strcmp(name, c.name) == 0) {
708            if (isCategorySupported(c)) {
709                g_categoryEnables[i] = enable;
710                return true;
711            } else {
712                if (isCategorySupportedForRoot(c)) {
713                    fprintf(stderr, "error: category \"%s\" requires root "
714                            "privileges.\n", name);
715                } else {
716                    fprintf(stderr, "error: category \"%s\" is not supported "
717                            "on this device.\n", name);
718                }
719                return false;
720            }
721        }
722    }
723    fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
724    return false;
725}
726
727static bool setCategoriesEnableFromFile(const char* categories_file)
728{
729    if (!categories_file) {
730        return true;
731    }
732    Tokenizer* tokenizer = NULL;
733    if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
734        return false;
735    }
736    bool ok = true;
737    while (!tokenizer->isEol()) {
738        String8 token = tokenizer->nextToken(" ");
739        if (token.isEmpty()) {
740            tokenizer->skipDelimiters(" ");
741            continue;
742        }
743        ok &= setCategoryEnable(token.string(), true);
744    }
745    delete tokenizer;
746    return ok;
747}
748
749// Set all the kernel tracing settings to the desired state for this trace
750// capture.
751static bool setUpTrace()
752{
753    bool ok = true;
754
755    // Set up the tracing options.
756    ok &= setCategoriesEnableFromFile(g_categoriesFile);
757    ok &= setTraceOverwriteEnable(g_traceOverwrite);
758    ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
759    ok &= setGlobalClockEnable(true);
760    ok &= setPrintTgidEnableIfPresent(true);
761    ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
762
763    // Set up the tags property.
764    uint64_t tags = 0;
765    for (int i = 0; i < NELEM(k_categories); i++) {
766        if (g_categoryEnables[i]) {
767            const TracingCategory &c = k_categories[i];
768            tags |= c.tags;
769        }
770    }
771    ok &= setTagsProperty(tags);
772
773    bool coreServicesTagEnabled = false;
774    for (int i = 0; i < NELEM(k_categories); i++) {
775        if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
776            coreServicesTagEnabled = g_categoryEnables[i];
777        }
778    }
779
780    std::string packageList(g_debugAppCmdLine);
781    if (coreServicesTagEnabled) {
782        char value[PROPERTY_VALUE_MAX];
783        property_get(k_coreServicesProp, value, "");
784        if (!packageList.empty()) {
785            packageList += ",";
786        }
787        packageList += value;
788    }
789    ok &= setAppCmdlineProperty(&packageList[0]);
790    ok &= pokeBinderServices();
791    pokeHalServices();
792
793    // Disable all the sysfs enables.  This is done as a separate loop from
794    // the enables to allow the same enable to exist in multiple categories.
795    ok &= disableKernelTraceEvents();
796
797    // Enable all the sysfs enables that are in an enabled category.
798    for (int i = 0; i < NELEM(k_categories); i++) {
799        if (g_categoryEnables[i]) {
800            const TracingCategory &c = k_categories[i];
801            for (int j = 0; j < MAX_SYS_FILES; j++) {
802                const char* path = c.sysfiles[j].path;
803                bool required = c.sysfiles[j].required == REQ;
804                if (path != NULL) {
805                    if (fileIsWritable(path)) {
806                        ok &= setKernelOptionEnable(path, true);
807                    } else if (required) {
808                        fprintf(stderr, "error writing file %s\n", path);
809                        ok = false;
810                    }
811                }
812            }
813        }
814    }
815
816    return ok;
817}
818
819// Reset all the kernel tracing settings to their default state.
820static void cleanUpTrace()
821{
822    // Disable all tracing that we're able to.
823    disableKernelTraceEvents();
824
825    // Reset the system properties.
826    setTagsProperty(0);
827    clearAppProperties();
828    pokeBinderServices();
829
830    // Set the options back to their defaults.
831    setTraceOverwriteEnable(true);
832    setTraceBufferSizeKB(1);
833    setGlobalClockEnable(false);
834    setPrintTgidEnableIfPresent(false);
835    setKernelTraceFuncs(NULL);
836}
837
838
839// Enable tracing in the kernel.
840static bool startTrace()
841{
842    return setTracingEnabled(true);
843}
844
845// Disable tracing in the kernel.
846static void stopTrace()
847{
848    setTracingEnabled(false);
849}
850
851// Read data from the tracing pipe and forward to stdout
852static void streamTrace()
853{
854    char trace_data[4096];
855    int traceFD = open(k_traceStreamPath, O_RDWR);
856    if (traceFD == -1) {
857        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
858                strerror(errno), errno);
859        return;
860    }
861    while (!g_traceAborted) {
862        ssize_t bytes_read = read(traceFD, trace_data, 4096);
863        if (bytes_read > 0) {
864            write(STDOUT_FILENO, trace_data, bytes_read);
865            fflush(stdout);
866        } else {
867            if (!g_traceAborted) {
868                fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
869                        bytes_read, errno, strerror(errno));
870            }
871            break;
872        }
873    }
874}
875
876// Read the current kernel trace and write it to stdout.
877static void dumpTrace(int outFd)
878{
879    ALOGI("Dumping trace");
880    int traceFD = open(k_tracePath, O_RDWR);
881    if (traceFD == -1) {
882        fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
883                strerror(errno), errno);
884        return;
885    }
886
887    if (g_compress) {
888        z_stream zs;
889        memset(&zs, 0, sizeof(zs));
890
891        int result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
892        if (result != Z_OK) {
893            fprintf(stderr, "error initializing zlib: %d\n", result);
894            close(traceFD);
895            return;
896        }
897
898        constexpr size_t bufSize = 64*1024;
899        std::unique_ptr<uint8_t> in(new uint8_t[bufSize]);
900        std::unique_ptr<uint8_t> out(new uint8_t[bufSize]);
901        if (!in || !out) {
902            fprintf(stderr, "couldn't allocate buffers\n");
903            close(traceFD);
904            return;
905        }
906
907        int flush = Z_NO_FLUSH;
908
909        zs.next_out = reinterpret_cast<Bytef*>(out.get());
910        zs.avail_out = bufSize;
911
912        do {
913
914            if (zs.avail_in == 0) {
915                // More input is needed.
916                result = read(traceFD, in.get(), bufSize);
917                if (result < 0) {
918                    fprintf(stderr, "error reading trace: %s (%d)\n",
919                            strerror(errno), errno);
920                    result = Z_STREAM_END;
921                    break;
922                } else if (result == 0) {
923                    flush = Z_FINISH;
924                } else {
925                    zs.next_in = reinterpret_cast<Bytef*>(in.get());
926                    zs.avail_in = result;
927                }
928            }
929
930            if (zs.avail_out == 0) {
931                // Need to write the output.
932                result = write(outFd, out.get(), bufSize);
933                if ((size_t)result < bufSize) {
934                    fprintf(stderr, "error writing deflated trace: %s (%d)\n",
935                            strerror(errno), errno);
936                    result = Z_STREAM_END; // skip deflate error message
937                    zs.avail_out = bufSize; // skip the final write
938                    break;
939                }
940                zs.next_out = reinterpret_cast<Bytef*>(out.get());
941                zs.avail_out = bufSize;
942            }
943
944        } while ((result = deflate(&zs, flush)) == Z_OK);
945
946        if (result != Z_STREAM_END) {
947            fprintf(stderr, "error deflating trace: %s\n", zs.msg);
948        }
949
950        if (zs.avail_out < bufSize) {
951            size_t bytes = bufSize - zs.avail_out;
952            result = write(outFd, out.get(), bytes);
953            if ((size_t)result < bytes) {
954                fprintf(stderr, "error writing deflated trace: %s (%d)\n",
955                        strerror(errno), errno);
956            }
957        }
958
959        result = deflateEnd(&zs);
960        if (result != Z_OK) {
961            fprintf(stderr, "error cleaning up zlib: %d\n", result);
962        }
963    } else {
964        ssize_t sent = 0;
965        while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
966        if (sent == -1) {
967            fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
968                    errno);
969        }
970    }
971
972    close(traceFD);
973}
974
975static void handleSignal(int /*signo*/)
976{
977    if (!g_nohup) {
978        g_traceAborted = true;
979    }
980}
981
982static void registerSigHandler()
983{
984    struct sigaction sa;
985    sigemptyset(&sa.sa_mask);
986    sa.sa_flags = 0;
987    sa.sa_handler = handleSignal;
988    sigaction(SIGHUP, &sa, NULL);
989    sigaction(SIGINT, &sa, NULL);
990    sigaction(SIGQUIT, &sa, NULL);
991    sigaction(SIGTERM, &sa, NULL);
992}
993
994static void listSupportedCategories()
995{
996    for (int i = 0; i < NELEM(k_categories); i++) {
997        const TracingCategory& c = k_categories[i];
998        if (isCategorySupported(c)) {
999            printf("  %10s - %s\n", c.name, c.longname);
1000        }
1001    }
1002}
1003
1004// Print the command usage help to stderr.
1005static void showHelp(const char *cmd)
1006{
1007    fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
1008    fprintf(stderr, "options include:\n"
1009                    "  -a appname      enable app-level tracing for a comma "
1010                        "separated list of cmdlines\n"
1011                    "  -b N            use a trace buffer size of N KB\n"
1012                    "  -c              trace into a circular buffer\n"
1013                    "  -f filename     use the categories written in a file as space-separated\n"
1014                    "                    values in a line\n"
1015                    "  -k fname,...    trace the listed kernel functions\n"
1016                    "  -n              ignore signals\n"
1017                    "  -s N            sleep for N seconds before tracing [default 0]\n"
1018                    "  -t N            trace for N seconds [default 5]\n"
1019                    "  -z              compress the trace dump\n"
1020                    "  --async_start   start circular trace and return immediatly\n"
1021                    "  --async_dump    dump the current contents of circular trace buffer\n"
1022                    "  --async_stop    stop tracing and dump the current contents of circular\n"
1023                    "                    trace buffer\n"
1024                    "  --stream        stream trace to stdout as it enters the trace buffer\n"
1025                    "                    Note: this can take significant CPU time, and is best\n"
1026                    "                    used for measuring things that are not affected by\n"
1027                    "                    CPU performance, like pagecache usage.\n"
1028                    "  --list_categories\n"
1029                    "                  list the available tracing categories\n"
1030                    " -o filename      write the trace to the specified file instead\n"
1031                    "                    of stdout.\n"
1032            );
1033}
1034
1035int main(int argc, char **argv)
1036{
1037    bool async = false;
1038    bool traceStart = true;
1039    bool traceStop = true;
1040    bool traceDump = true;
1041    bool traceStream = false;
1042
1043    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
1044        showHelp(argv[0]);
1045        exit(0);
1046    }
1047
1048    for (;;) {
1049        int ret;
1050        int option_index = 0;
1051        static struct option long_options[] = {
1052            {"async_start",     no_argument, 0,  0 },
1053            {"async_stop",      no_argument, 0,  0 },
1054            {"async_dump",      no_argument, 0,  0 },
1055            {"list_categories", no_argument, 0,  0 },
1056            {"stream",          no_argument, 0,  0 },
1057            {           0,                0, 0,  0 }
1058        };
1059
1060        ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
1061                          long_options, &option_index);
1062
1063        if (ret < 0) {
1064            for (int i = optind; i < argc; i++) {
1065                if (!setCategoryEnable(argv[i], true)) {
1066                    fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
1067                    exit(1);
1068                }
1069            }
1070            break;
1071        }
1072
1073        switch(ret) {
1074            case 'a':
1075                g_debugAppCmdLine = optarg;
1076            break;
1077
1078            case 'b':
1079                g_traceBufferSizeKB = atoi(optarg);
1080            break;
1081
1082            case 'c':
1083                g_traceOverwrite = true;
1084            break;
1085
1086            case 'f':
1087                g_categoriesFile = optarg;
1088            break;
1089
1090            case 'k':
1091                g_kernelTraceFuncs = optarg;
1092            break;
1093
1094            case 'n':
1095                g_nohup = true;
1096            break;
1097
1098            case 's':
1099                g_initialSleepSecs = atoi(optarg);
1100            break;
1101
1102            case 't':
1103                g_traceDurationSeconds = atoi(optarg);
1104            break;
1105
1106            case 'z':
1107                g_compress = true;
1108            break;
1109
1110            case 'o':
1111                g_outputFile = optarg;
1112            break;
1113
1114            case 0:
1115                if (!strcmp(long_options[option_index].name, "async_start")) {
1116                    async = true;
1117                    traceStop = false;
1118                    traceDump = false;
1119                    g_traceOverwrite = true;
1120                } else if (!strcmp(long_options[option_index].name, "async_stop")) {
1121                    async = true;
1122                    traceStart = false;
1123                } else if (!strcmp(long_options[option_index].name, "async_dump")) {
1124                    async = true;
1125                    traceStart = false;
1126                    traceStop = false;
1127                } else if (!strcmp(long_options[option_index].name, "stream")) {
1128                    traceStream = true;
1129                    traceDump = false;
1130                } else if (!strcmp(long_options[option_index].name, "list_categories")) {
1131                    listSupportedCategories();
1132                    exit(0);
1133                }
1134            break;
1135
1136            default:
1137                fprintf(stderr, "\n");
1138                showHelp(argv[0]);
1139                exit(-1);
1140            break;
1141        }
1142    }
1143
1144    registerSigHandler();
1145
1146    if (g_initialSleepSecs > 0) {
1147        sleep(g_initialSleepSecs);
1148    }
1149
1150    bool ok = true;
1151    ok &= setUpTrace();
1152    ok &= startTrace();
1153
1154    if (ok && traceStart) {
1155        if (!traceStream) {
1156            printf("capturing trace...");
1157            fflush(stdout);
1158        }
1159
1160        // We clear the trace after starting it because tracing gets enabled for
1161        // each CPU individually in the kernel. Having the beginning of the trace
1162        // contain entries from only one CPU can cause "begin" entries without a
1163        // matching "end" entry to show up if a task gets migrated from one CPU to
1164        // another.
1165        ok = clearTrace();
1166
1167        writeClockSyncMarker();
1168        if (ok && !async && !traceStream) {
1169            // Sleep to allow the trace to be captured.
1170            struct timespec timeLeft;
1171            timeLeft.tv_sec = g_traceDurationSeconds;
1172            timeLeft.tv_nsec = 0;
1173            do {
1174                if (g_traceAborted) {
1175                    break;
1176                }
1177            } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
1178        }
1179
1180        if (traceStream) {
1181            streamTrace();
1182        }
1183    }
1184
1185    // Stop the trace and restore the default settings.
1186    if (traceStop)
1187        stopTrace();
1188
1189    if (ok && traceDump) {
1190        if (!g_traceAborted) {
1191            printf(" done\n");
1192            fflush(stdout);
1193            int outFd = STDOUT_FILENO;
1194            if (g_outputFile) {
1195                outFd = open(g_outputFile, O_WRONLY | O_CREAT);
1196            }
1197            if (outFd == -1) {
1198                printf("Failed to open '%s', err=%d", g_outputFile, errno);
1199            } else {
1200                dprintf(outFd, "TRACE:\n");
1201                dumpTrace(outFd);
1202                if (g_outputFile) {
1203                    close(outFd);
1204                }
1205            }
1206        } else {
1207            printf("\ntrace aborted.\n");
1208            fflush(stdout);
1209        }
1210        clearTrace();
1211    } else if (!ok) {
1212        fprintf(stderr, "unable to start tracing\n");
1213    }
1214
1215    // Reset the trace buffer size to 1.
1216    if (traceStop)
1217        cleanUpTrace();
1218
1219    return g_traceAborted ? 1 : 0;
1220}
1221